예제 #1
0
static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
{
	/* Variables */
	FT_Face face;
	const FT_ULong charcode_reserve = 256;
	FT_ULong charcode = 0, lcode;
	FT_UInt glyph_index;
	const char *fontname;
	VFontData *vfd;

#if 0
	FT_CharMap found = 0;
	FT_CharMap charmap;
	FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
	FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
	int n;
#endif

	/* load the freetype font */
	err = FT_New_Memory_Face(library,
	                         pf->data,
	                         pf->size,
	                         0,
	                         &face);

	if (err) return NULL;

#if 0
	for (n = 0; n < face->num_charmaps; n++)
	{
		charmap = face->charmaps[n];
		if (charmap->platform_id == my_platform_id &&
		    charmap->encoding_id == my_encoding_id)
		{
			found = charmap;
			break;
		}
	}

	if (!found) { return NULL; }

	/* now, select the charmap for the face object */
	err = FT_Set_Charmap(face, found);
	if (err) { return NULL; }
#endif

	/* allocate blender font */
	vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");

	/* get the name */
	fontname = FT_Get_Postscript_Name(face);
	BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name));

	/* Extract the first 256 character from TTF */
	lcode = charcode = FT_Get_First_Char(face, &glyph_index);

	/* No charmap found from the ttf so we need to figure it out */
	if (glyph_index == 0) {
		FT_CharMap found = NULL;
		FT_CharMap charmap;
		int n;

		for (n = 0; n < face->num_charmaps; n++) {
			charmap = face->charmaps[n];
			if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) {
				found = charmap;
				break;
			}
		}

		err = FT_Set_Charmap(face, found);

		if (err)
			return NULL;

		lcode = charcode = FT_Get_First_Char(face, &glyph_index);
	}


	/* Adjust font size */
	if (face->bbox.yMax != face->bbox.yMin) {
		vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
	}
	else {
		vfd->scale = 1.0f / 1000.0f;
	}

	/* Load characters */
	vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve);

	while (charcode < charcode_reserve) {
		/* Generate the font data */
		freetypechar_to_vchar(face, charcode, vfd);

		/* Next glyph */
		charcode = FT_Get_Next_Char(face, charcode, &glyph_index);

		/* Check that we won't start infinite loop */
		if (charcode <= lcode)
			break;
		lcode = charcode;
	}

	return vfd;
}
예제 #2
0
static void make_duplis_font(const DupliContext *ctx)
{
	Object *par = ctx->object;
	GHash *family_gh;
	Object *ob;
	Curve *cu;
	struct CharTrans *ct, *chartransdata = NULL;
	float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof;
	int text_len, a;
	size_t family_len;
	const wchar_t *text = NULL;
	bool text_free = false;

	/* font dupliverts not supported inside groups */
	if (ctx->group)
		return;

	copy_m4_m4(pmat, par->obmat);

	/* in par the family name is stored, use this to find the other objects */

	BKE_vfont_to_curve_ex(G.main, par, FO_DUPLI, NULL,
	                      &text, &text_len, &text_free, &chartransdata);

	if (text == NULL || chartransdata == NULL) {
		return;
	}

	cu = par->data;
	fsize = cu->fsize;
	xof = cu->xof;
	yof = cu->yof;

	ct = chartransdata;

	/* cache result */
	family_len = strlen(cu->family);
	family_gh = BLI_ghash_int_new_ex(__func__, 256);

	/* advance matching BLI_strncpy_wchar_from_utf8 */
	for (a = 0; a < text_len; a++, ct++) {

		ob = find_family_object(cu->family, family_len, (unsigned int)text[a], family_gh);
		if (ob) {
			vec[0] = fsize * (ct->xof - xof);
			vec[1] = fsize * (ct->yof - yof);
			vec[2] = 0.0;

			mul_m4_v3(pmat, vec);

			copy_m4_m4(obmat, par->obmat);

			if (UNLIKELY(ct->rot != 0.0f)) {
				float rmat[4][4];

				zero_v3(obmat[3]);
				unit_m4(rmat);
				rotate_m4(rmat, 'Z', -ct->rot);
				mul_m4_m4m4(obmat, obmat, rmat);
			}

			copy_v3_v3(obmat[3], vec);

			make_dupli(ctx, ob, obmat, a, false, false);
		}
	}

	if (text_free) {
		MEM_freeN((void *)text);
	}

	BLI_ghash_free(family_gh, NULL, NULL);

	MEM_freeN(chartransdata);
}
예제 #3
0
파일: MOD_mask.c 프로젝트: wchargin/blender
static DerivedMesh *applyModifier(
        ModifierData *md, Object *ob,
        DerivedMesh *dm,
        ModifierApplyFlag UNUSED(flag))
{
	MaskModifierData *mmd = (MaskModifierData *)md;
	const bool found_test = (mmd->flag & MOD_MASK_INV) == 0;
	DerivedMesh *result = NULL;
	GHash *vertHash = NULL, *edgeHash, *polyHash;
	GHashIterator gh_iter;
	MDeformVert *dvert, *dv;
	int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0;
	int maxVerts, maxEdges, maxPolys;
	int i;

	const MVert *mvert_src;
	const MEdge *medge_src;
	const MPoly *mpoly_src;
	const MLoop *mloop_src;

	MPoly *mpoly_dst;
	MLoop *mloop_dst;
	MEdge *medge_dst;
	MVert *mvert_dst;

	int *loop_mapping;

	dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
	if (dvert == NULL) {
		return found_test ? CDDM_from_template(dm, 0, 0, 0, 0, 0) : dm;
	}

	/* Overview of Method:
	 *	1. Get the vertices that are in the vertexgroup of interest
	 *	2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
	 *	3. Make a new mesh containing only the mapping data
	 */

	/* get original number of verts, edges, and faces */
	maxVerts = dm->getNumVerts(dm);
	maxEdges = dm->getNumEdges(dm);
	maxPolys = dm->getNumPolys(dm);

	/* check if we can just return the original mesh
	 *	- must have verts and therefore verts assigned to vgroups to do anything useful
	 */
	if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
	    (maxVerts == 0) || BLI_listbase_is_empty(&ob->defbase))
	{
		return dm;
	}

	/* if mode is to use selected armature bones, aggregate the bone groups */
	if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */
		Object *oba = mmd->ob_arm;
		bPoseChannel *pchan;
		bDeformGroup *def;
		bool *bone_select_array;
		int bone_select_tot = 0;
		const int defbase_tot = BLI_listbase_count(&ob->defbase);

		/* check that there is armature object with bones to use, otherwise return original mesh */
		if (ELEM(NULL, oba, oba->pose, ob->defbase.first))
			return dm;

		/* determine whether each vertexgroup is associated with a selected bone or not
		 * - each cell is a boolean saying whether bone corresponding to the ith group is selected
		 * - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts)
		 */
		bone_select_array = MEM_malloc_arrayN((size_t)defbase_tot, sizeof(char), "mask array");

		for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
			pchan = BKE_pose_channel_find_name(oba->pose, def->name);
			if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
				bone_select_array[i] = true;
				bone_select_tot++;
			}
			else {
				bone_select_array[i] = false;
			}
		}

		/* verthash gives mapping from original vertex indices to the new indices (including selected matches only)
		 * key = oldindex, value = newindex
		 */
		vertHash = BLI_ghash_int_new_ex("mask vert gh", (unsigned int)maxVerts);

		/* add vertices which exist in vertexgroups into vertHash for filtering
		 * - dv = for each vertex, what vertexgroups does it belong to
		 * - dw = weight that vertex was assigned to a vertexgroup it belongs to
		 */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			MDeformWeight *dw = dv->dw;
			bool found = false;
			int j;

			/* check the groups that vertex is assigned to, and see if it was any use */
			for (j = 0; j < dv->totweight; j++, dw++) {
				if (dw->def_nr < defbase_tot) {
					if (bone_select_array[dw->def_nr]) {
						if (dw->weight != 0.0f) {
							found = true;
							break;
						}
					}
				}
			}

			if (found_test != found) {
				continue;
			}

			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}

		/* free temp hashes */
		MEM_freeN(bone_select_array);
	}
	else {  /* --- Using Nominated VertexGroup only --- */
		int defgrp_index = defgroup_name_index(ob, mmd->vgroup);

		/* if no vgroup (i.e. dverts) found, return the initial mesh */
		if (defgrp_index == -1)
			return dm;

		/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
		vertHash = BLI_ghash_int_new_ex("mask vert2 bh", (unsigned int)maxVerts);

		/* add vertices which exist in vertexgroup into ghash for filtering */
		for (i = 0, dv = dvert; i < maxVerts; i++, dv++) {
			const bool found = defvert_find_weight(dv, defgrp_index) != 0.0f;
			if (found_test != found) {
				continue;
			}

			/* add to ghash for verts (numVerts acts as counter for mapping) */
			BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
			numVerts++;
		}
	}

	/* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
	edgeHash = BLI_ghash_int_new_ex("mask ed2 gh", (unsigned int)maxEdges);
	polyHash = BLI_ghash_int_new_ex("mask fa2 gh", (unsigned int)maxPolys);

	mvert_src = dm->getVertArray(dm);
	medge_src = dm->getEdgeArray(dm);
	mpoly_src = dm->getPolyArray(dm);
	mloop_src = dm->getLoopArray(dm);

	/* overalloc, assume all polys are seen */
	loop_mapping = MEM_malloc_arrayN((size_t)maxPolys, sizeof(int), "mask loopmap");

	/* loop over edges and faces, and do the same thing to
	 * ensure that they only reference existing verts
	 */
	for (i = 0; i < maxEdges; i++) {
		const MEdge *me = &medge_src[i];

		/* only add if both verts will be in new mesh */
		if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
		    BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
		{
			BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
			numEdges++;
		}
	}
	for (i = 0; i < maxPolys; i++) {
		const MPoly *mp_src = &mpoly_src[i];
		const MLoop *ml_src = &mloop_src[mp_src->loopstart];
		bool ok = true;
		int j;

		for (j = 0; j < mp_src->totloop; j++, ml_src++) {
			if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml_src->v))) {
				ok = false;
				break;
			}
		}

		/* all verts must be available */
		if (ok) {
			BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys));
			loop_mapping[numPolys] = numLoops;
			numPolys++;
			numLoops += mp_src->totloop;
		}
	}


	/* now we know the number of verts, edges and faces,
	 * we can create the new (reduced) mesh
	 */
	result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys);

	mpoly_dst = CDDM_get_polys(result);
	mloop_dst = CDDM_get_loops(result);
	medge_dst = CDDM_get_edges(result);
	mvert_dst = CDDM_get_verts(result);

	/* using ghash-iterators, map data into new mesh */
	/* vertices */
	GHASH_ITER (gh_iter, vertHash) {
		const MVert *v_src;
		MVert *v_dst;
		const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
		const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));

		v_src = &mvert_src[i_src];
		v_dst = &mvert_dst[i_dst];

		*v_dst = *v_src;
		DM_copy_vert_data(dm, result, i_src, i_dst, 1);
	}

	/* edges */
	GHASH_ITER (gh_iter, edgeHash) {
		const MEdge *e_src;
		MEdge *e_dst;
		const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
		const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));

		e_src = &medge_src[i_src];
		e_dst = &medge_dst[i_dst];

		DM_copy_edge_data(dm, result, i_src, i_dst, 1);
		*e_dst = *e_src;
		e_dst->v1 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v1)));
		e_dst->v2 = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(e_src->v2)));
	}

	/* faces */
	GHASH_ITER (gh_iter, polyHash) {
		const int i_src = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&gh_iter));
		const int i_dst = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
		const MPoly *mp_src = &mpoly_src[i_src];
		MPoly *mp_dst = &mpoly_dst[i_dst];
		const int i_ml_src = mp_src->loopstart;
		const int i_ml_dst = loop_mapping[i_dst];
		const MLoop *ml_src = &mloop_src[i_ml_src];
		MLoop *ml_dst = &mloop_dst[i_ml_dst];

		DM_copy_poly_data(dm, result, i_src, i_dst, 1);
		DM_copy_loop_data(dm, result, i_ml_src, i_ml_dst, mp_src->totloop);

		*mp_dst = *mp_src;
		mp_dst->loopstart = i_ml_dst;
		for (i = 0; i < mp_src->totloop; i++) {
			ml_dst[i].v = GET_UINT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_UINT_IN_POINTER(ml_src[i].v)));
			ml_dst[i].e = GET_UINT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_UINT_IN_POINTER(ml_src[i].e)));
		}
	}

	MEM_freeN(loop_mapping);

	/* why is this needed? - campbell */
	/* recalculate normals */
	result->dirty |= DM_DIRTY_NORMALS;

	/* free hashes */
	BLI_ghash_free(vertHash, NULL, NULL);
	BLI_ghash_free(edgeHash, NULL, NULL);
	BLI_ghash_free(polyHash, NULL, NULL);

	/* return the new mesh */
	return result;
}