COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 10-12-2017, 10:07 AM   #1
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default Adding custom fonts to Cairo

I'm wanting to change the font used within Cairo, and have been examining the various font face functions but am getting a bit lost and not sure where to begin. Also, is it possible to import a TrueType font or is it all FreeType?
Bobflip is offline   Reply With Quote
Old 10-12-2017, 10:30 AM   #2
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by Bobflip View Post
I'm wanting to change the font used within Cairo, and have been examining the various font face functions but am getting a bit lost and not sure where to begin. Also, is it possible to import a TrueType font or is it all FreeType?
Don't know anything about it, but since FreeType supports TrueType, that should be the answer to the second question.
earlevel is offline   Reply With Quote
Old 10-12-2017, 11:03 AM   #3
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Ah, well that's a start, cheers!
Bobflip is offline   Reply With Quote
Old 10-13-2017, 02:52 AM   #4
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Look at ycairo_text class if you are using my framework... The best way for using is to create global font in plugin constructor.
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-13-2017, 02:26 PM   #5
MSK
Human being with feelings
 
Join Date: Jan 2017
Posts: 43
Default

This is how I set a global font using Youlean's branch.

In the plugin constructor:
Code:
   // Youlean's Cairo base
  ycairo_base * base = GetYCAIRO();
  
  // Create base font - this is used in all ycairo_text instances throughout
  base -> create_global_font_from_path("/Library/Fonts/Futura.ttc");
Then in a control you'd want some thinglike this:
Code:
 
// In the control constructor
ycairo_text * yText = new ycairo_text(ycairo_base);

// In the Draw() method
yText -> ycairo_show_text(cr, textChar, textSize, IRECT);
Hope that helps!
MSK

Last edited by MSK; 10-13-2017 at 02:33 PM.
MSK is offline   Reply With Quote
Old 10-14-2017, 05:26 AM   #6
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Quote:
Originally Posted by MSK View Post
This is how I set a global font using Youlean's branch.

In the plugin constructor:
Code:
   // Youlean's Cairo base
  ycairo_base * base = GetYCAIRO();
  
  // Create base font - this is used in all ycairo_text instances throughout
  base -> create_global_font_from_path("/Library/Fonts/Futura.ttc");
Then in a control you'd want some thinglike this:
Code:
 
// In the control constructor
ycairo_text * yText = new ycairo_text(ycairo_base);

// In the Draw() method
yText -> ycairo_show_text(cr, textChar, textSize, IRECT);
Hope that helps!
MSK
This is how I am using it:

Code:
class SomeControl: public IControl, ycairo_gui, ycairo_text
{
public:
	SomeControl(IPlugBase* pPlug, ycairo_base *ycairo_base, IRECT pR)
		: IControl(pPlug, pR), ycairo_gui(ycairo_base, this), ycairo_text(ycairo_base) {}
}
BTW you should never create object with new if you don't really need to. If you want to create object just use ycairo_text textObject;
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 05:31 AM   #7
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Creating global font from path is also not ideal. It would be best to ship font with your binary. To do that use:

resource.h
Code:
// Font declaration ---------------------------------------------------------------------
#define FONT_FILE 256  //Must be greater than 255, it should be declared once
#define FONT_ID 102 //Unique ID
#define FONT_PATH "resources/SomeFont.ttf"
//-------------------------------------------------------------------------------------
*.rc
Code:
#include "resource.h"

FONT_ID             FONT_FILE             FONT_PATH
constructor
Code:
GetYCAIRO()->create_global_font_from_memory(FONT_ID, FONT_FILE, FONT_PATH);
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 07:08 AM   #8
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Thanks everyone for the advice, I'll experiment this weekend, and I certainly plan to ship the font within the binaries.

Up to now I've been using cairo_text_path to draw text, is this compatible with the techniques described, or will I have to do a hefty session of rewriting?
Bobflip is offline   Reply With Quote
Old 10-14-2017, 07:35 AM   #9
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Quote:
Originally Posted by Bobflip View Post
Thanks everyone for the advice, I'll experiment this weekend, and I certainly plan to ship the font within the binaries.

Up to now I've been using cairo_text_path to draw text, is this compatible with the techniques described, or will I have to do a hefty session of rewriting?
Filling text path is very expensive on CPU (up to 1000% CPU increase), so you should switch to my methods (ycairo_show_text).
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 07:45 AM   #10
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Blimey, hahaha! Ok, definitely sorting that this weekend.

Although that said, I've been using the paths to create an outline around the text like this:

Code:
	// Outline text
	cairo_move_to(cr, mDrawRECT.L + x, mDrawRECT.T + y);
	cairo_text_path(cr, mStr.Get());
	cairo_fill_preserve(cr);
	cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
	cairo_set_line_width(cr, 2.56);
	cairo_stroke(cr);

	// Overlaid non-outline text
	cairo_move_to(cr, mDrawRECT.L + x, mDrawRECT.T + y);
	cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
	cairo_text_path(cr, mStr.Get());
	cairo_fill_preserve(cr);
	cairo_set_line_width(cr, 0.0);
	cairo_stroke(cr);
I can't see a way of doing this directly with ycairo_show_text, although maybe it's possible with ycairo_drop_shadow_stroke?
Bobflip is offline   Reply With Quote
Old 10-14-2017, 07:57 AM   #11
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Quote:
Originally Posted by Bobflip View Post
I can't see a way of doing this directly with ycairo_show_text, although maybe it's possible with ycairo_drop_shadow_stroke?
No drop shadow will be even more taxing on CPU. IF you want to outline text you need to use paths. you should look inside ycairo_show_text method to see how to create path with freetype.
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 08:10 AM   #12
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

That's the thing, I had a look in there but couldn't work out how to get a path from it, it's a bit over my head at this point.

Code:
void ycairo_text::ycairo_show_text(cairo_t * cr, const char * text, double size, IColor color, IRECT rect, ycairo_text_w_aligement w_aligement, ycairo_text_h_aligement h_aligement)

{
	cairo_set_source_rgba(cr, color.R / 255.0, color.G / 255.0, color.B / 255.0, color.A / 255.0);

	ycairo_initialize_font_face(cr);
	cairo_set_font_size(cr, size);
	ycairo_set_text(cr, text);
	ycairo_set_text_position(cr, rect, w_aligement, h_aligement);

	//// Adding subpixel rendering improves rendering speed by 10% on my system
	//cairo_font_options_t *options;
	//cairo_get_font_options(cr, options);

	//cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
	//cairo_set_font_options(cr, options);
	//// -----------------------------------------------------------------------

	cairo_show_text(cr, text);

	ycairo_destroy_font_face();
}

void ycairo_text::ycairo_show_text(cairo_t * cr)
{
	cairo_show_text(cr, draw_text);
}
Bobflip is offline   Reply With Quote
Old 10-14-2017, 08:14 AM   #13
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

[QUOTE=Bobflip;1898128]That's the thing, I had a look in there but couldn't work out how to get a path from it, it's a bit over my head at this point.

Read https://www.cairographics.org/manual/index.html


Anyways use cairo_text_path instead of cairo_show_text
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 08:26 AM   #14
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

I think that may have been where I learnt how to do it initially! The tutorials there were really handy while learning my way around Cairo.

I'm already using cairo_text_path in the code I posted above (post #10), I guess I could speed things up by using ycairo_show_text for the non-outline text and just use the path for the outline.
Bobflip is offline   Reply With Quote
Old 10-14-2017, 08:43 AM   #15
Youlean
Human being with feelings
 
Youlean's Avatar
 
Join Date: May 2015
Location: Serbia
Posts: 654
Default

Quote:
Originally Posted by Bobflip View Post
I think that may have been where I learnt how to do it initially! The tutorials there were really handy while learning my way around Cairo.

I'm already using cairo_text_path in the code I posted above (post #10), I guess I could speed things up by using ycairo_show_text for the non-outline text and just use the path for the outline.
Indeed but you will also speed up things if you use freetype to create font instead of cairo fonts.
__________________
Website | Facebook Page | IPlug-Youlean
Youlean is offline   Reply With Quote
Old 10-14-2017, 09:57 AM   #16
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Ok, thanks, will get that on the to-do list.

Having trouble creating the font still though, so I've pasted the code into the relevant bits of a fresh IPlugEffect, dropped a font into resources and dragged it into XCode's resources, and updated FONT_PATH to match, but on both Windows and Mac it bombs out with a Bad Access error at if (global_font) in create_global_font_from_memory.
Bobflip is offline   Reply With Quote
Old 10-14-2017, 10:09 AM   #17
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Actually, wait. I put it into IPlugEffectCairoGraphics (where I was originally doing the font testing!) and it loads ok, but it wasn't working in my plugin yet. Just going to get the font loading working in IPlugEffectCairoGraphics for now and then try and extrapolate it to mine!
Bobflip is offline   Reply With Quote
Old 10-14-2017, 11:19 AM   #18
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Ok yeah, got it sorted in both the example and in my own code! Not been able to get the cairo path text to line up with the ycairo text, but this seems to do the trick nicely. Thanks for the pointers.

Code:
		ycairo_prepare_draw();
		ycairo_initialize_font_face(cr);
		cairo_set_font_size(cr, 12);
		
		cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND);
		cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
		
		// Find coordinates to centre text
		cairo_text_extents_t extents;
		cairo_text_extents(cr, outputString, &extents);
		double x = (mDrawRECT.W() / 2) - (extents.width / 2 + extents.x_bearing);
		cairo_text_extents (cr, "0", &extents); // This gets the vertical centre but ignores the tails on a lower case 'p', for example
		double y = (mDrawRECT.H() / 2) - (extents.height / 2 + extents.y_bearing);

		// Round off the coordinates to prevent blurring.
		x = floor(x);
		y = floor(y);

		// Outline text
		cairo_move_to(cr, mDrawRECT.L + x, mDrawRECT.T + y);
		cairo_text_path(cr, outputString);
		cairo_fill_preserve(cr);
		cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
		cairo_set_line_width(cr, 2.56);
		cairo_stroke(cr);

		// Overlaid non-outline text
		cairo_move_to(cr, mDrawRECT.L + x, mDrawRECT.T + y);
		cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
		cairo_text_path(cr, outputString);
		cairo_fill_preserve(cr);
		cairo_set_line_width(cr, 0.0);
		cairo_stroke(cr);


		ycairo_draw();
		return true;

Last edited by Bobflip; 11-12-2017 at 08:37 PM.
Bobflip is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:59 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.