Outline Font OT_BaseLine data not found

This forum is for general developer support questions.
Post Reply
blmara
Posts: 76
Joined: Thu Jun 23, 2011 9:03 am
Location: Vantaa, Finland

Outline Font OT_BaseLine data not found

Post by blmara »

Hi,

in my program I use Text() replacement for font kerning and outputting Unicode glyphs. Fonts are handled through diskfont.library/bullet.library routines. As the bullet.library doesn't seem to support underlining (and for other reasons) I need to find the baseline of font. The query seems to fail, while other type of query works ok. Here is VBCC/GCC compilable example:

Code: Select all

/* outline font baseline test */
/* gcc  testolfont.c -o ram:test -lauto */

#include <stdio.h>
#include <proto/exec.h>
#include <proto/diskfont.h>
#include <diskfont/diskfonttag.h>
#include <diskfont/oterrors.h>

STRPTR fname = "Dejavu Sans Mono.font";
uint32 devdpi = 72<<16|72;
uint32 ptheight = 16;
//struct DiskfontIFace *IDiskfont;

int main()
{
	struct OutlineFont *olfont;

	olfont = IDiskfont->OpenOutlineFont(fname,NULL,OFF_OPEN);
	if (olfont)
	{
		if (!IDiskfont->ESetInfo(&olfont->olf_EEngine,OT_DeviceDPI,devdpi,OT_PointHeight,ptheight << 16,TAG_END))
		{
			printf("Font %s point height %lu opened successfully!\n",fname,ptheight);
			{
				int Ascend, Descend;
 				ULONG BaseLine,NumGlyphs;

 				if (!IDiskfont->EObtainInfo(&olfont->olf_EEngine,OT_BaseLine, &BaseLine, TAG_END) && ((BaseLine & 0xffff0000) != 0))
				{
 					Ascend = BaseLine >> 16;
 					Descend = BaseLine & 0xffff;
					printf("Font ascend %d, descend %d\n",Ascend,Descend);
				}
				else
				{
					printf("Couldn't get font baseline data!\n");
				}
				if (!IDiskfont->EObtainInfo(&olfont->olf_EEngine, OT_NumGlyphs, &NumGlyphs, TAG_END))
					printf("The font contains %lu glyphs\n", NumGlyphs);
				else
					printf("The font engine does not support OT_NumGlyphs\n");	

			}
			IDiskfont->CloseOutlineFont(olfont,NULL);
		}
	}
	return(1);
}

The OT_BaseLine seems to return always 0, but the font seems to have ascender/descender data as show by TypeManager. Why? The example is modified from diskfont/diskfonttag.h.

Marko
Marko
User avatar
javierdlr
Beta Tester
Beta Tester
Posts: 389
Joined: Sun Jun 19, 2011 10:13 pm
Location: Donostia (GUIPUZCOA) - Spain
Contact:

Re: Outline Font OT_BaseLine data not found

Post by javierdlr »

Can you try this:

Code: Select all

 struct TextAttr ta = {0};
 struct TextFont *font;

 ta.ta_Name = fname;
 ta.ta_YSize = ptheight;
 if( (font=IDiskfont->OpenDiskFont(&ta)) )
 {
  printf("Font: '%s' %d (%sproportional)\n",font->tf_Message.mn_Node.ln_Name,
           font->tf_YSize,(font->tf_Flags&FPF_PROPORTIONAL)? "":"no ");
  printf("Baseline=%d\n",font->tf_Baseline);
 }
 IGraphics->CloseFont(font);
I get:
#test
Font: 'DejaVu Sans Mono.font' 20 (no proportional)
Baseline=14

Hope it helps somehow.
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 530
Joined: Sat Jun 18, 2011 3:12 pm
Location: Finland
Contact:

Re: Outline Font OT_BaseLine data not found

Post by salass00 »

TypeManager uses OT_BaseLine but also has fallback code which calculates the baseline based on the highest ascend and descend values of the glyphs if OT_BaseLine fails so I guess OT_BaseLine is not something that can be relied upon for all fonts.
blmara
Posts: 76
Joined: Thu Jun 23, 2011 9:03 am
Location: Vantaa, Finland

Re: Outline Font OT_BaseLine data not found

Post by blmara »

javierdlr wrote:Can you try this:

Code: Select all

 struct TextAttr ta = {0};
 struct TextFont *font;

 ta.ta_Name = fname;
 ta.ta_YSize = ptheight;
 if( (font=IDiskfont->OpenDiskFont(&ta)) )
 {
  printf("Font: '%s' %d (%sproportional)\n",font->tf_Message.mn_Node.ln_Name,
           font->tf_YSize,(font->tf_Flags&FPF_PROPORTIONAL)? "":"no ");
  printf("Baseline=%d\n",font->tf_Baseline);
 }
 IGraphics->CloseFont(font);
I get:
#test
Font: 'DejaVu Sans Mono.font' 20 (no proportional)
Baseline=14

Hope it helps somehow.
So, the OpenDiskFont() finds the baseline somehow while the code example based on include file comment doesn't. How does it do that?

Marko
Marko
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 530
Joined: Sat Jun 18, 2011 3:12 pm
Location: Finland
Contact:

Re: Outline Font OT_BaseLine data not found

Post by salass00 »

This should be about the same method that diskfont.library uses to calculate the font->tf_Baseline value:

https://gist.github.com/salass00/c5ed9b ... 02f9d8b5b3
blmara
Posts: 76
Joined: Thu Jun 23, 2011 9:03 am
Location: Vantaa, Finland

Re: Outline Font OT_BaseLine data not found

Post by blmara »

salass00 wrote:This should be about the same method that diskfont.library uses to calculate the font->tf_Baseline value:

https://gist.github.com/salass00/c5ed9b ... 02f9d8b5b3
Thanks! So, if I understood correctly, in this method every glyph in the current character set (256 chars) is looked at and the baseline is calculated based on their metrics. In my program I use internally UCS-4 character coding and the utility.library functions to be able to import UTF-8 coded strings from (MusicXML) files. In theory, such a string can contain characters that are from multiple character sets. This probably means that one would need to go through all glyphs of the font to be sure of the baseline? Do you know why the OT_BaseLine doesn't seem to provide this information?

Marko
Marko
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 530
Joined: Sat Jun 18, 2011 3:12 pm
Location: Finland
Contact:

Re: Outline Font OT_BaseLine data not found

Post by salass00 »

I'm adding this here just in case if someone finds this thread via a search engine (like I just did).

Rather than using tags to get outline font information, like OT_BaseLine, OT_IsFixed, OT_YSizeFacter, OT_SpaceWidth with EObtainInfo(), which won't work ever, these tags should be looked for in outlinefont->olf_OTagList.

The easiest way to do this is using the IUtility->GetTagData() function.
blmara
Posts: 76
Joined: Thu Jun 23, 2011 9:03 am
Location: Vantaa, Finland

Re: Outline Font OT_BaseLine data not found

Post by blmara »

@salass00

Thanks, will adapt my code to that information. Could this be added to the SDK unless it's there already?

Marko

Edit: odd enough, with the routine described below the EObtainInfo() results in a reasonable value with Dejavu Sans.font while the GetTagData results a OT_BaseLine of 0. Other tags return a non-zero value. Using AmigaOS4.1FinalUpd, diskfont.library 53.9

Code: Select all

uint32 FindDocFontBaseline(APTR doc,SGFONTNR fontnr)
{
	struct DocFontNode *dfnode;
	uint32 asc,desc,bas,bline;

	bline = 0;
	if (fontnr > 0)
	{
		for (dfnode = FIRST_NODE(S_GetAttr(doc,SGT_FontList));NEXT_NODE(dfnode);dfnode = NEXT_NODE(dfnode))
		{
			if (dfnode->Fontnr == fontnr)
			{
				bline = dfnode->Font.bline;
				if (!IDiskfont->EObtainInfo(&dfnode->Font.olfont->olf_EEngine, OT_BaseLine, &bas, TAG_END))
				{
					if ((bas & 0xffff0000) != 0)
					{
						asc = bas >> 16;
						desc = bas & 0xffff;
						bline = (dfnode->Ptheight * dfnode->Pisz / dfnode->Posz) * asc / (asc+desc);
					}
					D(bug("Success in FindDocFontBaseline/EObtainInfo!\n"));
				}
				else
				{
					D(bug("Using  FindDocFontBaseline/GetTagList method!\n"));
					bas = IUtility->GetTagData(OT_BaseLine,0,dfnode->Font.olfont->olf_OTagList);
					asc = bas >> 16;
					desc = bas & 0xffff;					
					bline = (dfnode->Ptheight * dfnode->Pisz / dfnode->Posz) * asc / (asc+desc);
				}
				D(bug("GetTagData baseline %ld\n",IUtility->GetTagData(OT_BaseLine,0,dfnode->Font.olfont->olf_OTagList)));
				D(bug("GetTagData ysizefactor %ld\n",IUtility->GetTagData(OT_YSizeFactor,0,dfnode->Font.olfont->olf_OTagList)));
				D(bug("GetTagData spacewidth  %ld\n",IUtility->GetTagData(OT_SpaceWidth,0,dfnode->Font.olfont->olf_OTagList)));
				D(bug("FindDocFontBaseline bline %ld\n",bline));
				break;
			}
		}
	}
    return(bline);
}
Marko
Marko
User avatar
salass00
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 530
Joined: Sat Jun 18, 2011 3:12 pm
Location: Finland
Contact:

Re: Outline Font OT_BaseLine data not found

Post by salass00 »

@blmara

I was wrong about OT_BaseLine. Apparently it is one of the tags which should be used with EObtainInfo().

Quoting from the <diskfont/diskfonttag.h> header:
/* ? OT_BaseLine returns the ascender in the upper 16 bit
* and the descender in the lower 16 bit so you can compute
* the baseline faster if the font engine supports this tag.
* Even if the tag is supported you must check whether the
* result contains a zero ascender.
* Example:
*
* int Ascend, Descend;
* ULONG BaseLine;
*
* if (!ObtainInfo(engineHandle, OT_BaseLine, &BaseLine, TAG_END) &&
* ((BaseLine & 0xffff0000) != 0))
* {
* Ascend = BaseLine >> 16;
* Descend = BaseLine & 0xffff;
* BaseLinePosInPixels =
* (LineHeightInPixels * Ascend) / (Ascend + Descend);
* }
* else
* {
* // assume the baseline from ascender and
* // descender values of a series of rendered glyphs as before
* }
*/
Post Reply