static void *ml_addview_cb(void *base, const char *str) { RenderResult *rr = base; RenderView *rv; rv = MEM_callocN(sizeof(RenderView), "new render view"); BLI_strncpy(rv->name, str, EXR_VIEW_MAXNAME); /* For stereo drawing we need to ensure: * STEREO_LEFT_NAME == STEREO_LEFT_ID and * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */ if (STREQ(str, STEREO_LEFT_NAME)) { BLI_addhead(&rr->views, rv); } else if (STREQ(str, STEREO_RIGHT_NAME)) { RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name)); if (left_rv == NULL) { BLI_addhead(&rr->views, rv); } else { BLI_insertlinkafter(&rr->views, left_rv, rv); } } else { BLI_addtail(&rr->views, rv); } return rv; }
static unsigned int *imb_thread_cache_get_tile(ImThreadTileCache *cache, ImBuf *ibuf, int tx, int ty) { ImThreadTile *ttile, lookuptile; ImGlobalTile *gtile, *replacetile; int toffs= ibuf->xtiles*ty + tx; /* test if it is already in our thread local cache */ if((ttile=cache->tiles.first)) { /* check last used tile before going to hash */ if(ttile->ibuf == ibuf && ttile->tx == tx && ttile->ty == ty) return ibuf->tiles[toffs]; /* find tile in hash */ lookuptile.ibuf = ibuf; lookuptile.tx = tx; lookuptile.ty = ty; if((ttile=BLI_ghash_lookup(cache->tilehash, &lookuptile))) { BLI_remlink(&cache->tiles, ttile); BLI_addhead(&cache->tiles, ttile); return ibuf->tiles[toffs]; } } /* not found, have to do slow lookup in global cache */ if(cache->unused.first == NULL) { ttile= cache->tiles.last; replacetile= ttile->global; BLI_remlink(&cache->tiles, ttile); BLI_ghash_remove(cache->tilehash, ttile, NULL, NULL); } else { ttile= cache->unused.first; replacetile= NULL; BLI_remlink(&cache->unused, ttile); } BLI_addhead(&cache->tiles, ttile); BLI_ghash_insert(cache->tilehash, ttile, ttile); gtile= imb_global_cache_get_tile(ibuf, tx, ty, replacetile); ttile->ibuf= gtile->ibuf; ttile->tx= gtile->tx; ttile->ty= gtile->ty; ttile->global= gtile; return ibuf->tiles[toffs]; }
/* duplicate selected TimeMarkers */ static void ed_marker_duplicate_apply(bContext *C, wmOperator *op) { ListBase *markers= context_get_markers(C); TimeMarker *marker, *newmarker; if (markers == NULL) return; /* go through the list of markers, duplicate selected markers and add duplicated copies * to the begining of the list (unselect original markers) */ for (marker= markers->first; marker; marker= marker->next) { if (marker->flag & SELECT) { /* unselect selected marker */ marker->flag &= ~SELECT; /* create and set up new marker */ newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); newmarker->flag= SELECT; newmarker->frame= marker->frame; BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name)); /* new marker is added to the begining of list */ BLI_addhead(markers, newmarker); } } }
static void group_linkobs2scene_cb(bContext *UNUSED(C), Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem) { Group *group = (Group *)tselem->id; GroupObject *gob; Base *base; for (gob = group->gobject.first; gob; gob = gob->next) { base = BKE_scene_base_find(scene, gob->ob); if (base) { base->object->flag |= SELECT; base->flag |= SELECT; } else { /* link to scene */ base = MEM_callocN(sizeof(Base), "add_base"); BLI_addhead(&scene->base, base); base->lay = gob->ob->lay; gob->ob->flag |= SELECT; base->flag = gob->ob->flag; base->object = gob->ob; id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */ } } }
/* duplicate selected TimeMarkers */ static void ed_marker_duplicate_apply(bContext *C) { ListBase *markers = ED_context_get_markers(C); TimeMarker *marker, *newmarker; if (markers == NULL) return; /* go through the list of markers, duplicate selected markers and add duplicated copies * to the beginning of the list (unselect original markers) */ for (marker = markers->first; marker; marker = marker->next) { if (marker->flag & SELECT) { /* unselect selected marker */ marker->flag &= ~SELECT; /* create and set up new marker */ newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); newmarker->flag = SELECT; newmarker->frame = marker->frame; BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name)); #ifdef DURIAN_CAMERA_SWITCH newmarker->camera = marker->camera; #endif /* new marker is added to the beginning of list */ // FIXME: bad ordering! BLI_addhead(markers, newmarker); } } }
/** * Run after saving a file to refresh the #BLENDER_HISTORY_FILE list. */ static void wm_history_file_update(void) { RecentFile *recent; /* no write history for recovered startup files */ if (G.main->name[0] == 0) return; recent = G.recent_files.first; /* refresh recent-files.txt of recent opened files, when current file was changed */ if (!(recent) || (BLI_path_cmp(recent->filepath, G.main->name) != 0)) { recent = wm_file_history_find(G.main->name); if (recent) { BLI_remlink(&G.recent_files, recent); } else { RecentFile *recent_next; for (recent = BLI_findlink(&G.recent_files, U.recent_files - 1); recent; recent = recent_next) { recent_next = recent->next; wm_history_file_free(recent); } recent = wm_history_file_new(G.main->name); } /* add current file to the beginning of list */ BLI_addhead(&(G.recent_files), recent); /* write current file to recent-files.txt */ wm_history_file_write(); /* also update most recent files on System */ GHOST_addToSystemRecentFiles(G.main->name); } }
/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) { Base *base, *baseNext; MPathTarget *mpt; /* make sure our temp-tag isn't already in use */ for (base= scene->base.first; base; base= base->next) base->object->flag &= ~BA_TEMP_TAG; /* for each target, dump its object to the start of the list if it wasn't moved already */ for (mpt= targets->first; mpt; mpt= mpt->next) { for (base=scene->base.first; base; base=baseNext) { baseNext = base->next; if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) { BLI_remlink(&scene->base, base); BLI_addhead(&scene->base, base); mpt->ob->flag |= BA_TEMP_TAG; break; // we really don't need to continue anymore once this happens, but this line might really 'break' } } } /* "brew me a list that's sorted a bit faster now depsy" */ DAG_scene_sort(G.main, scene); }
static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap) { wmKeyMapItem *kmi, *kmin; for(kmi=addonmap->items.first; kmi; kmi=kmi->next) { kmin = wm_keymap_item_copy(kmi); keymap_item_set_id(keymap, kmin); BLI_addhead(&keymap->items, kmin); } }
static void write_history(void) { struct RecentFile *recent, *next_recent; char name[FILE_MAX]; const char *user_config_dir; FILE *fp; int i; /* no write history for recovered startup files */ if (G.main->name[0] == 0) return; /* will be NULL in background mode */ user_config_dir = BLI_get_folder_create(BLENDER_USER_CONFIG, NULL); if (!user_config_dir) return; BLI_make_file_string("/", name, user_config_dir, BLENDER_HISTORY_FILE); recent = G.recent_files.first; /* refresh recent-files.txt of recent opened files, when current file was changed */ if (!(recent) || (BLI_path_cmp(recent->filepath, G.main->name) != 0)) { fp = BLI_fopen(name, "w"); if (fp) { /* add current file to the beginning of list */ recent = (RecentFile *)MEM_mallocN(sizeof(RecentFile), "RecentFile"); recent->filepath = BLI_strdup(G.main->name); BLI_addhead(&(G.recent_files), recent); /* write current file to recent-files.txt */ fprintf(fp, "%s\n", recent->filepath); recent = recent->next; i = 1; /* write rest of recent opened files to recent-files.txt */ while ((i < U.recent_files) && (recent)) { /* this prevents to have duplicities in list */ if (BLI_path_cmp(recent->filepath, G.main->name) != 0) { fprintf(fp, "%s\n", recent->filepath); recent = recent->next; } else { next_recent = recent->next; MEM_freeN(recent->filepath); BLI_freelinkN(&(G.recent_files), recent); recent = next_recent; } i++; } fclose(fp); } /* also update most recent files on System */ GHOST_addToSystemRecentFiles(G.main->name); } }
Base *BKE_scene_base_add(Scene *sce, Object *ob) { Base *b = MEM_callocN(sizeof(*b), "BKE_scene_base_add"); BLI_addhead(&sce->base, b); b->object = ob; b->flag = ob->flag; b->lay = ob->lay; return b; }
bUserMenu *BKE_blender_user_menu_ensure(ListBase *lb, char space_type, const char *context) { bUserMenu *um = BKE_blender_user_menu_find(lb, space_type, context); if (um == NULL) { um = MEM_callocN(sizeof(bUserMenu), __func__); um->space_type = space_type; STRNCPY(um->context, context); BLI_addhead(lb, um); } return um; }
void BLF_dir_add(const char *path) { DirBLF *dir; dir = blf_dir_find(path); if (dir) /* already in the list ? just return. */ return; dir = (DirBLF *)MEM_callocN(sizeof(DirBLF), "BLF_dir_add"); dir->path = BLI_strdup(path); BLI_addhead(&global_font_dir, dir); }
static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, bool any, bool shift, bool ctrl, bool alt, bool oskey, int keymodifier, bool head) { /* wmWindowManager *wm = CTX_wm_manager(C); */ wmKeyMapItem *kmi = NULL; char idname_bl[OP_MAX_TYPENAME]; int modifier = 0; /* only on non-modal maps */ if (km->flag & KEYMAP_MODAL) { BKE_report(reports, RPT_ERROR, "Not a non-modal keymap"); return NULL; } WM_operator_bl_idname(idname_bl, idname); if (shift) modifier |= KM_SHIFT; if (ctrl) modifier |= KM_CTRL; if (alt) modifier |= KM_ALT; if (oskey) modifier |= KM_OSKEY; if (any) modifier = KM_ANY; /* create keymap item */ kmi = WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); /* [#32437] allow scripts to define hotkeys that get added to start of keymap * so that they stand a chance against catch-all defines later on */ if (head) { BLI_remlink(&km->items, kmi); BLI_addhead(&km->items, kmi); } return kmi; }
static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority) { task_pool_num_increase(task->pool); /* add task to queue */ BLI_mutex_lock(&scheduler->queue_mutex); if (priority == TASK_PRIORITY_HIGH) BLI_addhead(&scheduler->queue, task); else BLI_addtail(&scheduler->queue, task); BLI_condition_notify_one(&scheduler->queue_cond); BLI_mutex_unlock(&scheduler->queue_mutex); }
static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh) { PropagateEdge *pedge = mesh->propagatestack.first; if(pedge) { *edge = pedge->edge; *vert = pedge->vert; BLI_remlink(&mesh->propagatestack, pedge); BLI_addhead(&mesh->reusestack, pedge); } else { *edge = NULL; *vert = NULL; } }
/* the python exec operator uses this */ static int console_history_cycle_exec(bContext *C, wmOperator *op) { SpaceConsole *sc = CTX_wm_space_console(C); ARegion *ar = CTX_wm_region(C); ConsoleLine *ci = console_history_verify(C); /* TODO - stupid, just prevents crashes when no command line */ const bool reverse = RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */ int prev_len = ci->len; /* keep a copy of the line above so when history is cycled * this is the only function that needs to know about the double-up */ if (ci->prev) { ConsoleLine *ci_prev = (ConsoleLine *)ci->prev; if (STREQ(ci->line, ci_prev->line)) console_history_free(sc, ci_prev); } if (reverse) { /* last item in history */ ci = sc->history.last; BLI_remlink(&sc->history, ci); BLI_addhead(&sc->history, ci); } else { ci = sc->history.first; BLI_remlink(&sc->history, ci); BLI_addtail(&sc->history, ci); } { /* add a duplicate of the new arg and remove all other instances */ ConsoleLine *cl; while ((cl = console_history_find(sc, ci->line, ci))) console_history_free(sc, cl); console_history_add(sc, (ConsoleLine *)sc->history.last); } ci = sc->history.last; console_select_offset(sc, ci->len - prev_len); /* could be wrapped so update scroll rect */ console_textview_update_rect(sc, ar); ED_area_tag_redraw(CTX_wm_area(C)); console_scroll_bottom(ar); return OPERATOR_FINISHED; }
/* Create a new glyph cache for the current size and dpi. */ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) { GlyphCacheBLF *gc; gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new"); gc->next = NULL; gc->prev = NULL; gc->size = font->size; gc->dpi = font->dpi; memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table)); memset(gc->bucket, 0, sizeof(gc->bucket)); gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__); gc->ntex = 256; gc->cur_tex = BLF_CURTEX_UNSET; gc->x_offs = 0; gc->y_offs = 0; gc->pad = 3; gc->num_glyphs = (int)font->face->num_glyphs; gc->rem_glyphs = (int)font->face->num_glyphs; gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f; gc->descender = ((float)font->face->size->metrics.descender) / 64.0f; if (FT_IS_SCALABLE(font->face)) { gc->max_glyph_width = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) * (((float)font->face->size->metrics.x_ppem) / ((float)font->face->units_per_EM))); gc->max_glyph_height = (int)((float)(font->face->bbox.yMax - font->face->bbox.yMin) * (((float)font->face->size->metrics.y_ppem) / ((float)font->face->units_per_EM))); } else { gc->max_glyph_width = (int)(((float)font->face->size->metrics.max_advance) / 64.0f); gc->max_glyph_height = (int)(((float)font->face->size->metrics.height) / 64.0f); } gc->p2_width = 0; gc->p2_height = 0; BLI_addhead(&font->cache, gc); return gc; }
/** * \brief Add a new Walker State * * Allocate a new empty state and put it on the worklist. * A pointer to the new state is returned so that the caller * can fill in the state data. The new state will be inserted * at the front for depth-first walks, and at the end for * breadth-first walks. */ void *BMW_state_add(BMWalker *walker) { BMwGenericWalker *newstate; newstate = BLI_mempool_alloc(walker->worklist); newstate->depth = walker->depth; switch (walker->order) { case BMW_DEPTH_FIRST: BLI_addhead(&walker->states, newstate); break; case BMW_BREADTH_FIRST: BLI_addtail(&walker->states, newstate); break; default: BLI_assert(0); break; } return newstate; }
static void writeBlog(void) { struct RecentFile *recent, *next_recent; char name[FILE_MAXDIR+FILE_MAXFILE]; FILE *fp; int i; BLI_make_file_string("/", name, BLI_gethome(), ".Blog"); recent = G.recent_files.first; /* refresh .Blog of recent opened files, when current file was changed */ if(!(recent) || (strcmp(recent->filename, G.sce)!=0)) { fp= fopen(name, "w"); if (fp) { /* add current file to the beginning of list */ recent = (RecentFile*)MEM_mallocN(sizeof(RecentFile),"RecentFile"); recent->filename = (char*)MEM_mallocN(sizeof(char)*(strlen(G.sce)+1), "name of file"); recent->filename[0] = '\0'; strcpy(recent->filename, G.sce); BLI_addhead(&(G.recent_files), recent); /* write current file to .Blog */ fprintf(fp, "%s\n", recent->filename); recent = recent->next; i=1; /* write rest of recent opened files to .Blog */ while((i<U.recent_files) && (recent)){ /* this prevents to have duplicities in list */ if (strcmp(recent->filename, G.sce)!=0) { fprintf(fp, "%s\n", recent->filename); recent = recent->next; } else { next_recent = recent->next; MEM_freeN(recent->filename); BLI_freelinkN(&(G.recent_files), recent); recent = next_recent; } i++; } fclose(fp); } } }
static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh) { PropagateEdge *pedge = mesh->reusestack.first; if(pedge) { BLI_remlink(&mesh->reusestack, pedge); } else { if(!mesh->arena) { mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "edgesplit arena"); BLI_memarena_use_calloc(mesh->arena); } pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge)); } pedge->edge = edge; pedge->vert = vert; BLI_addhead(&mesh->propagatestack, pedge); }
static wmKeyMapItem *rna_KeyMap_item_new_from_item(wmKeyMap *km, ReportList *reports, wmKeyMapItem *kmi_src, bool head) { /* wmWindowManager *wm = CTX_wm_manager(C); */ if ((km->flag & KEYMAP_MODAL) == (kmi_src->idname[0] != '\0')) { BKE_report(reports, RPT_ERROR, "Can not mix modal/non-modal items"); return NULL; } /* create keymap item */ wmKeyMapItem *kmi = WM_keymap_add_item_copy(km, kmi_src); if (head) { BLI_remlink(&km->items, kmi); BLI_addhead(&km->items, kmi); } return kmi; }
static Object *AddNewBlenderMesh(Scene *scene, Base *base) { // This little function adds a new mesh object to the blender object list // It uses ob to duplicate data as this seems to be easier than creating // a new one. This new oject contains no faces nor vertices. Mesh *old_me; Base *basen; Object *ob_new; // now create a new blender object. // duplicating all the settings from the previous object // to the new one. ob_new= copy_object(base->object); // Ok we don't want to use the actual data from the // last object, the above function incremented the // number of users, so decrement it here. old_me= ob_new->data; old_me->id.us--; // Now create a new base to add into the linked list of // vase objects. basen= MEM_mallocN(sizeof(Base), "duplibase"); *basen= *base; BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */ basen->object= ob_new; basen->flag &= ~SELECT; // Initialize the mesh data associated with this object. ob_new->data= add_mesh("Mesh"); // Finally assign the object type. ob_new->type= OB_MESH; return ob_new; }
static void group_linkobs2scene_cb(bContext *UNUSED(C), Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem) { Group *group= (Group *)tselem->id; GroupObject *gob; Base *base; for (gob=group->gobject.first; gob; gob=gob->next) { base= object_in_scene(gob->ob, scene); if (base) { base->object->flag |= SELECT; base->flag |= SELECT; } else { /* link to scene */ base= MEM_callocN( sizeof(Base), "add_base"); BLI_addhead(&scene->base, base); base->lay= (1<<20)-1; /*v3d->lay;*/ /* would be nice to use the 3d layer but the include's not here */ gob->ob->flag |= SELECT; base->flag = gob->ob->flag; base->object= gob->ob; id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */ } } }
static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); ParticleSystem *psys= ptr.data; ParticleSettings *part; ParticleDupliWeight *dw; if (!psys) return OPERATOR_CANCELLED; part = psys->part; for (dw=part->dupliweights.first; dw; dw=dw->next) { if (dw->flag & PART_DUPLIW_CURRENT) { dw->flag &= ~PART_DUPLIW_CURRENT; dw = MEM_dupallocN(dw); dw->flag |= PART_DUPLIW_CURRENT; BLI_addhead(&part->dupliweights, dw); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); break; } } return OPERATOR_FINISHED; }
GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) { FT_GlyphSlot slot; GlyphBLF *g; FT_Error err; FT_Bitmap bitmap, tempbitmap; const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0; int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; FT_BBox bbox; unsigned int key; g = blf_glyph_search(font->glyph_cache, c); if (g) return g; /* glyphs are dynamically created as needed by font rendering. this means that * to make font rendering thread safe we have to do locking here. note that this * must be a lock for the whole library and not just per font, because the font * renderer uses a shared buffer internally */ BLI_spin_lock(font->ft_lib_mutex); /* search again after locking */ g = blf_glyph_search(font->glyph_cache, c); if (g) { BLI_spin_unlock(font->ft_lib_mutex); return g; } if (font->flags & BLF_HINTING) flags &= ~FT_LOAD_NO_HINTING; if (is_sharp) err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); else err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); if (err) { BLI_spin_unlock(font->ft_lib_mutex); return NULL; } /* get the glyph. */ slot = font->face->glyph; if (is_sharp) { err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO); /* Convert result from 1 bit per pixel to 8 bit per pixel */ /* Accum errors for later, fine if not interested beyond "ok vs any error" */ FT_Bitmap_New(&tempbitmap); err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); /* Does Blender use Pitch 1 always? It works so far */ err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap); err += FT_Bitmap_Done(font->ft_lib, &tempbitmap); } else { err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); } if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) { BLI_spin_unlock(font->ft_lib_mutex); return NULL; } g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add"); g->c = c; g->idx = (FT_UInt)index; g->xoff = -1; g->yoff = -1; bitmap = slot->bitmap; g->width = (int)bitmap.width; g->height = (int)bitmap.rows; if (g->width && g->height) { if (is_sharp) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ int i; for (i = 0; i < (g->width * g->height); i++) { bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } g->bitmap = (unsigned char *)MEM_mallocN((size_t)(g->width * g->height), "glyph bitmap"); memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)(g->width * g->height)); } g->advance = ((float)slot->advance.x) / 64.0f; g->advance_i = (int)g->advance; g->pos_x = (float)slot->bitmap_left; g->pos_y = (float)slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); g->box.xmin = ((float)bbox.xMin) / 64.0f; g->box.xmax = ((float)bbox.xMax) / 64.0f; g->box.ymin = ((float)bbox.yMin) / 64.0f; g->box.ymax = ((float)bbox.yMax) / 64.0f; key = blf_hash(g->c); BLI_addhead(&(font->glyph_cache->bucket[key]), g); BLI_spin_unlock(font->ft_lib_mutex); return g; }
static void bli_builddir(const char *dirname, const char *relname) { struct dirent *fname; struct dirlink *dlink; int rellen, newnum = 0; char buf[256]; DIR *dir; BLI_strncpy(buf, relname, sizeof(buf)); rellen=strlen(relname); if (rellen) { buf[rellen]='/'; rellen++; } #ifndef WIN32 if (chdir(dirname) == -1) { perror(dirname); return; } #else UTF16_ENCODE(dirname); if (!SetCurrentDirectoryW(dirname_16)) { perror(dirname); free(dirname_16); return; } UTF16_UN_ENCODE(dirname); #endif if ((dir = (DIR *)opendir("."))) { while ((fname = (struct dirent*) readdir(dir)) != NULL) { dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); if (dlink) { BLI_strncpy(buf + rellen, fname->d_name, sizeof(buf) - rellen); dlink->name = BLI_strdup(buf); BLI_addhead(dirbase, dlink); newnum++; } } if (newnum) { if (files) { void *tmp = realloc(files, (totnum+newnum) * sizeof(struct direntry)); if (tmp) { files = (struct direntry *)tmp; } else { /* realloc fail */ free(files); files = NULL; } } if (files==NULL) files=(struct direntry *)malloc(newnum * sizeof(struct direntry)); if (files) { dlink = (struct dirlink *) dirbase->first; while (dlink) { memset(&files[actnum], 0, sizeof(struct direntry)); files[actnum].relname = dlink->name; files[actnum].path = BLI_strdupcat(dirname, dlink->name); // use 64 bit file size, only needed for WIN32 and WIN64. // Excluding other than current MSVC compiler until able to test #ifdef WIN32 {wchar_t * name_16 = alloc_utf16_from_8(dlink->name, 0); #if (defined(WIN32) || defined(WIN64)) && (_MSC_VER>=1500) _wstat64(name_16, &files[actnum].s); #elif defined(__MINGW32__) _stati64(dlink->name, &files[actnum].s); #endif free(name_16);}; #else stat(dlink->name, &files[actnum].s); #endif files[actnum].type=files[actnum].s.st_mode; files[actnum].flags = 0; totnum++; actnum++; dlink = dlink->next; } } else { printf("Couldn't get memory for dir\n"); exit(1); } BLI_freelist(dirbase); if (files) qsort(files, actnum, sizeof(struct direntry), (int (*)(const void *, const void*))bli_compare); } else { printf("%s empty directory\n", dirname); } closedir(dir); } else { printf("%s non-existant directory\n", dirname); } }
/** * Scans the directory named *dirname and appends entries for its contents to files. */ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) { struct ListBase dirbase = {NULL, NULL}; int newnum = 0; DIR *dir; if ((dir = opendir(dirname)) != NULL) { const struct dirent *fname; while ((fname = readdir(dir)) != NULL) { struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); if (dlink != NULL) { dlink->name = BLI_strdup(fname->d_name); BLI_addhead(&dirbase, dlink); newnum++; } } if (newnum) { if (dir_ctx->files) { void * const tmp = realloc(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); if (tmp) { dir_ctx->files = (struct direntry *)tmp; } else { /* realloc fail */ free(dir_ctx->files); dir_ctx->files = NULL; } } if (dir_ctx->files == NULL) dir_ctx->files = (struct direntry *)malloc(newnum * sizeof(struct direntry)); if (dir_ctx->files) { struct dirlink * dlink = (struct dirlink *) dirbase.first; struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; while (dlink) { char fullname[PATH_MAX]; memset(file, 0, sizeof(struct direntry)); file->relname = dlink->name; file->path = BLI_strdupcat(dirname, dlink->name); BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); // use 64 bit file size, only needed for WIN32 and WIN64. // Excluding other than current MSVC compiler until able to test #ifdef WIN32 { wchar_t *name_16 = alloc_utf16_from_8(fullname, 0); #if defined(_MSC_VER) && (_MSC_VER >= 1500) _wstat64(name_16, &file->s); #elif defined(__MINGW32__) _stati64(fullname, &file->s); #endif free(name_16); } #else stat(fullname, &file->s); #endif file->type = file->s.st_mode; file->flags = 0; dir_ctx->nrfiles++; file++; dlink = dlink->next; } } else { printf("Couldn't get memory for dir\n"); exit(1); } BLI_freelist(&dirbase); if (dir_ctx->files) { qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); } } else { printf("%s empty directory\n", dirname); } closedir(dir); } else { printf("%s non-existant directory\n", dirname); } }
/** * \param normal_proj Optional normal thats used to project the scanfill verts into 2d coords. * Pass this along if known since it saves time calculating the normal. * \param flipnormal Flip the normal (same as passing \a normal_proj negated) */ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj[3], const bool flipnormal) { ScanFillContext sf_ctx; ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last; ScanFillFace *sf_tri; MemArena *sf_arena; DispList *dlnew = NULL, *dl; float *f1; int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0; int totvert; const int scanfill_flag = BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_HOLES; if (dispbase == NULL) return; if (BLI_listbase_is_empty(dispbase)) return; sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); while (cont) { int dl_flag_accum = 0; cont = 0; totvert = 0; nextcol = 0; BLI_scanfill_begin_arena(&sf_ctx, sf_arena); dl = dispbase->first; while (dl) { if (dl->type == DL_POLY) { if (charidx < dl->charidx) cont = 1; else if (charidx == dl->charidx) { /* character with needed index */ if (colnr == dl->col) { sf_ctx.poly_nr++; /* make editverts and edges */ f1 = dl->verts; a = dl->nr; sf_vert = sf_vert_new = NULL; while (a--) { sf_vert_last = sf_vert; sf_vert = BLI_scanfill_vert_add(&sf_ctx, f1); totvert++; if (sf_vert_last == NULL) sf_vert_new = sf_vert; else { BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert); } f1 += 3; } if (sf_vert != NULL && sf_vert_new != NULL) { BLI_scanfill_edge_add(&sf_ctx, sf_vert, sf_vert_new); } } else if (colnr < dl->col) { /* got poly with next material at current char */ cont = 1; nextcol = 1; } } dl_flag_accum |= dl->flag; } dl = dl->next; } /* XXX (obedit && obedit->actcol) ? (obedit->actcol - 1) : 0)) { */ if (totvert && (tot = BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_proj))) { if (tot) { dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE)); dlnew->col = colnr; dlnew->nr = totvert; dlnew->parts = tot; dlnew->index = MEM_mallocN(tot * 3 * sizeof(int), "dlindex"); dlnew->verts = MEM_mallocN(totvert * 3 * sizeof(float), "dlverts"); /* vert data */ f1 = dlnew->verts; totvert = 0; for (sf_vert = sf_ctx.fillvertbase.first; sf_vert; sf_vert = sf_vert->next) { copy_v3_v3(f1, sf_vert->co); f1 += 3; /* index number */ sf_vert->tmp.i = totvert; totvert++; } /* index data */ index = dlnew->index; for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { index[0] = sf_tri->v1->tmp.i; index[1] = sf_tri->v2->tmp.i; index[2] = sf_tri->v3->tmp.i; if (flipnormal) SWAP(int, index[0], index[2]); index += 3; } } BLI_addhead(to, dlnew); } BLI_scanfill_end_arena(&sf_ctx, sf_arena); if (nextcol) { /* stay at current char but fill polys with next material */ colnr++; } else { /* switch to next char and start filling from first material */ charidx++; colnr = 0; } } BLI_memarena_free(sf_arena); /* do not free polys, needed for wireframe display */ }
/* Helper func to extract an RNA path from selected tree element * NOTE: the caller must zero-out all values of the pointers that it passes here first, as * this function does not do that yet */ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, ID **id, char **path, int *array_index, short *flag, short *UNUSED(groupmode)) { ListBase hierarchy = {NULL, NULL}; LinkData *ld; TreeElement *tem, *temnext, *temsub; TreeStoreElem *tse, *tsenext; PointerRNA *ptr, *nextptr; PropertyRNA *prop; char *newpath=NULL; /* optimise tricks: * - Don't do anything if the selected item is a 'struct', but arrays are allowed */ if (tselem->type == TSE_RNA_STRUCT) return; /* Overview of Algorithm: * 1. Go up the chain of parents until we find the 'root', taking note of the * levels encountered in reverse-order (i.e. items are added to the start of the list * for more convenient looping later) * 2. Walk down the chain, adding from the first ID encountered * (which will become the 'ID' for the KeyingSet Path), and build a * path as we step through the chain */ /* step 1: flatten out hierarchy of parents into a flat chain */ for (tem= te->parent; tem; tem= tem->parent) { ld= MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()"); ld->data= tem; BLI_addhead(&hierarchy, ld); } /* step 2: step down hierarchy building the path (NOTE: addhead in previous loop was needed so that we can loop like this) */ for (ld= hierarchy.first; ld; ld= ld->next) { /* get data */ tem= (TreeElement *)ld->data; tse= TREESTORE(tem); ptr= &tem->rnaptr; prop= tem->directdata; /* check if we're looking for first ID, or appending to path */ if (*id) { /* just 'append' property to path * - to prevent memory leaks, we must write to newpath not path, then free old path + swap them */ if(tse->type == TSE_RNA_PROPERTY) { if(RNA_property_type(prop) == PROP_POINTER) { /* for pointer we just append property name */ newpath= RNA_path_append(*path, ptr, prop, 0, NULL); } else if(RNA_property_type(prop) == PROP_COLLECTION) { char buf[128], *name; temnext= (TreeElement*)(ld->next->data); tsenext= TREESTORE(temnext); nextptr= &temnext->rnaptr; name= RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf)); if(name) { /* if possible, use name as a key in the path */ newpath= RNA_path_append(*path, NULL, prop, 0, name); if(name != buf) MEM_freeN(name); } else { /* otherwise use index */ int index= 0; for(temsub=tem->subtree.first; temsub; temsub=temsub->next, index++) if(temsub == temnext) break; newpath= RNA_path_append(*path, NULL, prop, index, NULL); } ld= ld->next; } } if(newpath) { if (*path) MEM_freeN(*path); *path= newpath; newpath= NULL; } } else { /* no ID, so check if entry is RNA-struct, and if that RNA-struct is an ID datablock to extract info from */ if (tse->type == TSE_RNA_STRUCT) { /* ptr->data not ptr->id.data seems to be the one we want, since ptr->data is sometimes the owner of this ID? */ if(RNA_struct_is_ID(ptr->type)) { *id= (ID *)ptr->data; /* clear path */ if(*path) { MEM_freeN(*path); path= NULL; } } } } } /* step 3: if we've got an ID, add the current item to the path */ if (*id) { /* add the active property to the path */ ptr= &te->rnaptr; prop= te->directdata; /* array checks */ if (tselem->type == TSE_RNA_ARRAY_ELEM) { /* item is part of an array, so must set the array_index */ *array_index= te->index; } else if (RNA_property_array_length(ptr, prop)) { /* entire array was selected, so keyframe all */ *flag |= KSP_FLAG_WHOLE_ARRAY; } /* path */ newpath= RNA_path_append(*path, NULL, prop, 0, NULL); if (*path) MEM_freeN(*path); *path= newpath; } /* free temp data */ BLI_freelistN(&hierarchy); }
static ImGlobalTile *imb_global_cache_get_tile(ImBuf *ibuf, int tx, int ty, ImGlobalTile *replacetile) { ImGlobalTile *gtile, lookuptile; BLI_mutex_lock(&GLOBAL_CACHE.mutex); if(replacetile) replacetile->refcount--; /* find tile in global cache */ lookuptile.ibuf = ibuf; lookuptile.tx = tx; lookuptile.ty = ty; gtile= BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile); if(gtile) { /* found tile. however it may be in the process of being loaded by another thread, in that case we do stupid busy loop waiting for the other thread to load the tile */ gtile->refcount++; BLI_mutex_unlock(&GLOBAL_CACHE.mutex); while(gtile->loading) ; } else { /* not found, let's load it from disk */ /* first check if we hit the memory limit */ if(GLOBAL_CACHE.maxmem && GLOBAL_CACHE.totmem > GLOBAL_CACHE.maxmem) { /* find an existing tile to unload */ for(gtile=GLOBAL_CACHE.tiles.last; gtile; gtile=gtile->prev) if(gtile->refcount == 0 && gtile->loading == 0) break; } if(gtile) { /* found a tile to unload */ imb_global_cache_tile_unload(gtile); BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL); BLI_remlink(&GLOBAL_CACHE.tiles, gtile); } else { /* allocate a new tile or reuse unused */ if(GLOBAL_CACHE.unused.first) { gtile= GLOBAL_CACHE.unused.first; BLI_remlink(&GLOBAL_CACHE.unused, gtile); } else gtile= BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile)); } /* setup new tile */ gtile->ibuf= ibuf; gtile->tx= tx; gtile->ty= ty; gtile->refcount= 1; gtile->loading= 1; BLI_ghash_insert(GLOBAL_CACHE.tilehash, gtile, gtile); BLI_addhead(&GLOBAL_CACHE.tiles, gtile); /* mark as being loaded and unlock to allow other threads to load too */ GLOBAL_CACHE.totmem += sizeof(unsigned int)*ibuf->tilex*ibuf->tiley; BLI_mutex_unlock(&GLOBAL_CACHE.mutex); /* load from disk */ imb_global_cache_tile_load(gtile); /* mark as done loading */ gtile->loading= 0; } return gtile; }