In this article I show you how to use multilingual UTF-8 strings with standard, unmodified OpenAccess oa-22.04p028 release.
In the last article, I introduced UTF-8, the popular 8 bit encoding of Unicode into multibyte character strings that can represent virtually every written language in history. I presented the OpenAccess software changes required to fully support UTF-8 and showed you how to convert your existing application software to properly manipulate UTF-8 in the OpenAccess oaString class.
UTF-8 with Standard OpenAccess
You can write an internationalized application based on any standard OpenAccess release by following these simple rules:
- Upon startup, get the locale from the user environment using,
setlocale(LC_CTYPE, "");
If you are using an application framework, it may set the locale for you. For example, Qt QApplication sets the locale.
- Only use oaString methods that do not involve a count
- Perform string manipulations that do involve a count in a Unicode compatible string class like std::string or Qt QString. You can in fact use many of the oaString methods that involve a count with UTF-8, but it hardly seems worth the risk and confusion.
- Only ASCII strings should be converted to oaNames using OpenAccess namespaces. The resulting oaNames generally end up in netlists, and you don’t want a non-ASCII netlist. Most namespaces tell you about a non-ASCII character by throwing an exception.
- If you must use an OpenAccess namespace with a non-ASCII string, use oaNativeNS
That’s all you need to do. You may already be coding this way.
As a demonstration vehicle, I used vView™, a Qt application that creates a design containing an oaText object, and then displays it. vView further provides the ability to modify the oaText object.
OpenAccess Text Objects
Now let’s look at rendering text. OpenAccess provides three classes that represent text displayed on the screen of a graphics editor:
- oaText
- oaEvalText
- oaTextDisplay (base class)
Bounding Box Calculator
Like all oaShapes, text objects have a bounding box. Since each graphical application renders text on the screen differently, OpenAccess cannot know how big it will appear. Therefore the application must provide implementations for the oaText::getBBox()
and oaTextDisplay::getBBox()
methods.
The bounding box calculator can be provided as either a plugin, or as an in-memory instance. I first made a plugin, but due to the close coupling between the bounding box calculator and text rendering software, I switched to the in-memory model. Perhaps the best thing about the in-memory model is that it is compiled into your application where it will not get lost. The OpenAccess plugin search process is a constant source of trouble for developers and users alike.
Translating oaString to QString
When translating a string from an OpenAccess oaString to a Qt QString, use:
QString qString(QString::fromUtf8(static_cast<const char*> (oString)));
Finding the Text Bounding Box
The Qt QFontMetrics::boundingRect()
method returns a text bounding box based on the font, size, and of course the string itself. I could not get QFontMetrics::boundingRect()
to work with any text alignment except upperLeft, so I transformed the bounding box according to the OpenAccess oaTextAlign text alignment myself.
Translating oaFont to QFont Family
The OpenAccess font types provided an unwelcome opportunity to exercise artistic license. I did a bit of research and used the following mapping to Qt font families, keeping in mind that Japanese and Chinese fonts come in only a few varieties due to the large number of characters they contain. Still, you can rely on QFont to always select a reasonable font from among those installed:
const char* qtText::getQFontFamily(const oaFont &oFont){ switch (static_cast<oaFontEnum>(oFont)) { case oacEuroStyleFont: // San serif but actually more mid-century modern return "Sans Serif"; case oacGothicFont: // Obvious choice return "Sans Serif"; case oacMathFont: // Open to interpretation return "Sans Serif"; case oacRomanFont: // Obvious choice return "Serif"; case oacScriptFont: // Open to interpretation return "Cursive"; case oacStickFont: // Open to interpretation return "Sans Serif"; case oacFixedFont: // Obvious choice return "Monospace"; case oacSwedishFont: // The IKEA logo uses san serif, so thaar you go return "Sans Serif"; case oacMilSpecFont: // Lettering that meets US DoD mil-std-130 should be // all capitals in a sans-serif font return "Sans Serif"; }}
If you (especially Cadence Virtuoso people) would like to share your recommended font mapping, please share it with us in a comment.
Text Rendering
Text rendering is performed with Qt QPainter. Convert the oaString to a QString as shown above, and draw it with QPainter::drawText()
.
Translating QString to oaString
When you create an oaText or change its text value, translate the Qt QString to an OpenAccess oaString containing UTF-8. For example, to set the string value of an existing oaText:
oaString oString(static_cast<const char*>(text.toUtf8()));if (oString.isEmpty()) { // An empty oaText object is forbidden oString = " ";}oText->setText(oString);
Note how I use just the oaString constructor, assignment operator, and isEmpty()
, none of which involve a count.
UTF-8 in an OpenAccess oaName
Most oaNameSpaces do not allow non-ASCII characters–they throw an exception when they encounter one. The exception is the oaNativeNS. I do not recommend non-ASCII names that might appear in netlists, but just for amusement I used a Japanese name for the design created within vView:
- Library name and library path “ライブラリ” (“library” in Japanese)
- Cell name “設計” (“design” in Chinese or Japanese)
- View name “layout”. I use English here because non-standard view names are just wrong.
It works. The OpenAccess maskLayout viewType is on disk in file,
ライブラリ/#e8#a8#ad#e8#a8#88/layout/layout.oa
where “#e8#a8#ad#e8#a8#88” is the OpenAccess namespace ‘#’ encoding of cell name “設計”. Also, the lib.defs library definition file properly relates the ‘#’ encoded OpenAccess library name to file path “ライブラリ”:
DEFINE #e3#83#a9#e3#82#a4#e3#83#96#e3#83#a9#e3#83#aa ライブラリ
Amusing indeed.
Comments
Post a Comment