Copy SUTextRef Error

when I copy SUTextRef from b.skp to a.skp, the program error.
when I don’t copy SUTextRef, it’s ok.

SDK

SDK_WIN_x64_2021-0-339

Code

#include <SketchUpAPI\sketchup.h>
#include <cstdio>
#include <assert.h>

#define SU(api_function_call) {\
  SUResult su_api_result = api_function_call;\
  assert(SU_ERROR_NONE == su_api_result);\
}\

#define refute(condition) assert(!(condition))

std::string sustr2str(SUStringRef str) {
	size_t str_len = 0;
	SUResult res = SUStringGetUTF8Length(str, &str_len);
	if (res != SU_ERROR_NONE) return NULL;
	char* str_char = new char[str_len + 1];
	SUStringGetUTF8(str, str_len, str_char, &str_len);
	if (res != SU_ERROR_NONE) {
		delete[] str_char;
		return NULL;
	}
	str_char[str_len] = '\0';
	std::string string(str_char);
	if (str_char) delete[] str_char;
	return string;
}

SUStringRef str2sustr(std::string str) {
	SUStringRef resstr = SU_INVALID;
	SUResult res = SUStringCreateFromUTF8(&resstr, str.c_str());
	if (res == SU_ERROR_NONE) return resstr;
	return SU_INVALID;
}

void CopyText(SUTextRef src_text, SUTextRef * dest_text)
{
	SUStringRef text_str = SU_INVALID;
	SU(SUStringCreate(&text_str));
	SU(SUTextGetString(src_text, &text_str));
	SU(SUTextSetString(*dest_text, sustr2str(text_str).c_str()));
	SU(SUStringRelease(&text_str));

	SUFontRef text_font = SU_INVALID;
	SU(SUTextGetFont(src_text, &text_font));
	SU(SUTextSetFont(*dest_text, text_font));

	SUTextLeaderType leader;
	SU(SUTextGetLeaderType(src_text, &leader));
	SU(SUTextSetLeaderType(*dest_text, leader));

	SUArrowType arrow_type;
	SU(SUTextGetArrowType(src_text, &arrow_type));
	SU(SUTextSetArrowType(*dest_text, arrow_type));

	SUInstancePathRef src_path = SU_INVALID;
	//SUInstancePathRef path = SU_INVALID;
	SUPoint3D point;
	SU(SUTextGetPoint(src_text, &point, &src_path));
	//SU(SUInstancePathCreateCopy(&path, src_path));
	SU(SUTextSetPoint(*dest_text, &point, SU_INVALID));
	SU(SUInstancePathRelease(&src_path));
	//SU(SUInstancePathRelease(&path));


	if (leader == SUTextLeaderType_None) {
		double percent_x = 0, percent_y = 0;
		SU(SUTextGetScreenPosition(src_text, &percent_x, &percent_y));
		SU(SUTextSetScreenPosition(*dest_text, percent_x, percent_y));
	}else {
		SUVector3D vector;
		SUResult res = SUTextGetLeaderVector(src_text, &vector);
		//SU(SUTextGetLeaderVector(src_text, &vector));
		SU(SUTextSetLeaderVector(*dest_text, &vector));
	}

	SUColor color;
	SU(SUTextGetColor(src_text, &color));
	SU(SUTextSetColor(*dest_text, &color));
}

bool AddTexts(SUEntitiesRef src_entities, SUEntitiesRef * dest_entities)
{
	size_t text_num = 0;
	SU(SUEntitiesGetNumTexts(src_entities,&text_num));
	if (text_num <= 0) return false;
	std::vector<SUTextRef> src_texts(text_num), texts;
	SU(SUEntitiesGetTexts(src_entities, text_num, &src_texts[0], &text_num));
	for (int i = 0; i < text_num; i++) {
		SUTextRef text = SU_INVALID;
		SU(SUTextCreate(&text));
		CopyText(src_texts[i], &text);
		texts.push_back(text);
	}
	SU(SUEntitiesAddTexts(*dest_entities,texts.size(),&texts[0]));
	return true;
}

int main() {
	// Always initialize the API before using it
	SUInitialize();
	// Load the model from a file
	SUResult res;
	SUModelRef model1 = SU_INVALID, model2 = SU_INVALID;
	SU(SUModelCreateFromFile(&model1, "F:/a.skp"));
	SU(SUModelCreateFromFile(&model2, "F:/b.skp"));

	SUEntitiesRef src_entities = SU_INVALID, dest_entities = SU_INVALID;
	SU(SUModelGetEntities(model2, &src_entities));
	SU(SUModelGetEntities(model1, &dest_entities));
	AddTexts(src_entities, &dest_entities);

	SU(SUModelSaveToFile(model1, "F:/new.skp"));
	SU(SUModelRelease(&model1));
	SU(SUModelRelease(&model2));
	SUTerminate();
	return 0;

}

ERROR

a.skp sketchup 2019

a.skp (528.1 KB)

b.skp sketchup 2019

b.skp (525.8 KB)

You need to copy the font object as well. It’s an Entity type (SketchUp C API: SUFontRef Struct Reference) and these can never be shared across models.

image

Can you elaborate please?

How does a program load a font into a SUModelRef ?

Are coders forced to use template models with fonts already loaded ?

1 Like

@tt_su
I know this, but no SUFontCreate* function.
I just ignore the error (ModelRelease and SUTerminate()) or not copy SUTextRef.

SU(SUModelSaveToFile(model1, "F:/new.skp"));
SU(SUModelRelease(&model1));
//SU(SUModelRelease(&model2));
//SUTerminate();
return 0;

An entity owned by another model should not be added to another model. You will end up with double-delete and get an access violation like in this case.

hm… I’ve not dealt with fonts myself, this part of the API is unfamiliar. I need to look closer at how fonts works.

Hm… there is SUModelGetNumFonts and SUModelGetFonts. But I see no way to managing fonts (adding/removing).

I know :wink: I wanted you to realize it also.

@tt_su
Is this (add/remove font) a missing API ?

1 Like

Correct, it is not yet implemented. I filed an issue on it over a year and a half ago …

2 Likes