[V8i API] Create text element with non-existing font name / generate font number of missing font by name

Hello, is there a way to create a text element with font that is not currently available?

Let's say I need to create a text element which uses 'simplex' font in first version of MicroStation V8i where normally is installed only one SHX font - 'msdefault'. 

I have tried all methods (I can imagine) in MDL and API as well to get a font number using name 'simplex' but always I try to find font by name I get NULL instead of FontP.

This is what I do:

  MSDgnFileP dgnFile = FontManager::GetMSDgnFileP(model);
  FontNumMapP fontNumMap = FontManager::GetFontMap(dgnFile);
  UInt32 num = 0xFFFFFFFF;
  FontP font = fontNumMap->FindFontByName(&num, (MSWCharCP)L"simplex", FINDFONT_All);

font is NULL...

  • Unknown said:

    is there a way to create a text element with font that is not currently available?

    IMHO it's not a good idea because you may face an origin/range calculation issue (I suppose that Microstation misses some font information).

    Unknown said:

    I have tried all methods (I can imagine) in MDL and API as well to get a font number using name 'simplex' but always I try to find font by name I get NULL instead of FontP.

    This is what I do:

      MSDgnFileP dgnFile = FontManager::GetMSDgnFileP(model);
      FontNumMapP fontNumMap = FontManager::GetFontMap(dgnFile);
      UInt32 num = 0xFFFFFFFF;
      FontP font = fontNumMap->FindFontByName(&num, (MSWCharCP)L"simplex", FINDFONT_All);

    font is NULL...

    I used following workaround to "install" some font in similar situation few years ago:

    • create temporary DGN file and fill font table element with required font records
    • open temporary file and retrieve instance of FontP for required font
    • use FontNumMap.GetFontNumber with addIfNotFound=TRUE for font mapping of the target DGN file

    HTH

    Regards, Vit

  • Hello Vit, thanks for reply...

    Could you please suggest how I can fill font table element?

    Thanks.

  • Hi DanPaul,

    I used following code snippets. It's really MDL style programmming :(

    status = mdlWorkDgn_openFile (&modelRef, NULL, NULL, pathA, NULL, FALSE);
    status = mdlTable_getUniqueTableElm (&fontTableDsc, NULL, modelRef, MS_FONT_TABLE_LEVEL);
    UInt lastId = 0;
    status = mdlTable_getHighestEntryId (&lastId, fontTableDsc);
    ...
    MSElementDescr *entryDesc = NULL;
    id = 0;
    status = mdlTable_getNextEntryId (&id, fontTableDsc, lastId);
    if (id == lastId)
    {
       id++;
    }
    lastId = id;
    int size = 23 + fontNameLength;
    memset (&el, 0, 2 * size);
    el.hdr.ehdr.level = MS_FONT_TABLE_LEVEL;
    el.hdr.ehdr.type = TABLE_ENTRY_ELM;
    el.hdr.ehdr.elementSize = size;
    el.hdr.ehdr.attrOffset = size;
    el.buf[20] = (__int16) (id & 0xFFFF);
    el.buf[21] = (__int16) (id >> 16);
    el.buf[22] = 2 * (__int16)fontNameLength;
    for (int index = 0; index < fontNameLength; index++)
    {
       el.buf[23 + index] = fontName[index];
    }
    status = mdlElmdscr_new (&entryDesc, NULL, &el);
    status = mdlTableEntry_validateDescriptor (entryDesc);
    status = mdlTable_addEntryDescriptorToChain (fontTableDsc, entryDesc);

    Let me know if you find better way :)

    Regards Vit

    Answer Verified By: DanPaul 

  • I used to use the same method (FindFontByName) and it works as long as the font is loaded in MicroStation. Here's a better way which loads the font as long as it exists in one of the folders MicroStation scans for fonts (MS_FONTPATH):

    extern "C" DLLEXPORT int GetFontByName (char *fontName )
    {
        Bentley::Ustn::Text::FontNumMap* fonts = Bentley::Ustn::Text::FontManager::GetFontMap(mdlModelRef_getActive());
        UInt32      fnum = -666;
        Bentley::WString wFontName(fontName);

        FontCP font = Text::FontManager::FindSystemFont(wFontName.c_str());
        if (font == NULL) return(-1);

        fonts->GetFontNumber(fnum, *font, TRUE);
        return(fnum);
    }