Hot Door CORE Forum
Translating Unicode between std::string and ai::UnicodeString - Printable Version

+- Hot Door CORE Forum (http://hotdoorcore.com/forum)
+-- Forum: All forums (http://hotdoorcore.com/forum/forumdisplay.php?fid=1)
+--- Forum: Getting started (http://hotdoorcore.com/forum/forumdisplay.php?fid=6)
+--- Thread: Translating Unicode between std::string and ai::UnicodeString (/showthread.php?tid=336)



Translating Unicode between std::string and ai::UnicodeString - Rick Johnson - 02-10-2023

There are times when a plugin must use the SDK to get the name of a swatch or other string not accessible via CORE, where it's passed as an ai::UnicodeString. I typically use ai::UnicodeString.as_Platform() method to export it to an std::string in order to display it in a panel or dialog, or to compare the ai::UnicodeString to an std::string the user entered into a CORE text field.

If the user is in Europe or Asia or just enters an extended accented character, however, that often fails.

For example, say a custom color has this name:
 
     Maße
 
In the SDK I may get its name like so:


     err = sAICustomColor->GetCustomColorName(cColor, cName);
     std::string colorStr = cName.as_Platform();
 
I may get this:
 
    Ma√üe
 
or this:
 
    Ma\xa7e
 
If I put the ai::UnicodeString into a text frame using SDK code and get its contents through CORE, then I get an std::string with the correct accent characters.

Here's my current convoluted method of copying text from ai::UnicodeString to std::string:


Code:
ai::UnicodeString spot_string; // this is already populated with extended-character encoded text
const ai::UnicodeString::UTF16Char* utf16buffer;
hdi::core::LayerUP artLayer = HDI_CORE_ILLUSTRATOR->currentDocument()->firstLayer();
bool wasLocked = artLayer->locked();
bool wasVisible = artLayer->visible();
artLayer->setLocked(false);
artLayer->setVisible(true);
hdi::core::ArtSP tmpArt = hdi::core::draw::text("", hdi::core::ArtboardPoint(0,0), "", 8, hdi::core::JustifyLeft, hdi::core::ArtColor::black(),artLayer->group().get());
AIArtHandle tmpTextFrame = tmpArt->aiArtHandle();
TextRangeRef tempRange = NULL;
AIErr error = sAITextFrame->GetATETextRange(tmpTextFrame, &tempRange);
ITextRange irange(tempRange);
irange.Remove();
ai::UnicodeString::size_type tmpsz = sAIUnicodeString->UTF_16(spot_name, utf16buffer);
irange.InsertAfter(utf16buffer, tmpsz);

std::string OK_spot_name = tmpArt->text()->textRange()->contents(); // <-------- this is where the correct text gets assigned

tmpArt->dispose();
artLayer->setLocked(wasLocked);
artLayer->setVisible(wasVisible);

Is there a straightforward way to translate text between an ai::UnicodeString and std::string, and reliably preserve non-ascii accent characters?

Would those methods change depending on the user's location, e.g., UTF-8 or UTF-16 in some countries, UTF-32 in others?
 
Any suggestions would be much appreciated. Code snippets would be a lifesaver!


RE: Translating Unicode between std::string and ai::UnicodeString - garrett - 02-12-2023

hdi_core is designed to use UTF-8 encoding basically everywhere, which is why you see proper strings when acquiring them via hdi_core. I strongly suggest you work in UTF-8 whenever possible, falling back to UTF-16 or UTF-32 only when necessary. Platform encoding should be avoided (there are some edge cases where that is not possible, but this is not one of them).

Anyway, if you already have an ai::UnicodeString object, you need only call its as_UTF8() method to acquire a std::string in UTF-8 encoding.

If you have a UTF-8 encoded std::string and want to ensure proper construction of a new ai::UnicodeString object with it, pass it to the UnicodeString constructor followed by the kAIUTF8CharacterEncoding constant to indicate the encoding.