Use Multilingual UTF-8 Strings with any OpenAccess Version

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.

Japanese UTF-8 string in an oaText rendered in vView

Japanese oaText rendered in vView

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 I just can’t stand non-standard view names.

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.


This article was originally published by John McGehee, Voom, Inc. under the CC BY 3.0 license.  Changes have been made.