Пример #1
0
TextAsset::Size
TextAsset::computeSizeOfText(cairo_t* cairoContext,
                             const std::string textString,
                             int bounds,
                             PangoFontDescription* font,
                             Rect* tight,
                             float* lineHeightOut)
{
    PangoLayout* layout = pango_cairo_create_layout(cairoContext);

    // Kerning
    PangoAttrList* attr_list = pango_attr_list_new();
    PangoAttribute* spacing_attr = pango_attr_letter_spacing_new(pango_units_from_double(_kern));
    pango_attr_list_insert(attr_list, spacing_attr);
    pango_layout_set_attributes(layout, attr_list);

    pango_cairo_context_set_resolution(pango_layout_get_context(layout), DISPLAY_RESOLUTION);
    pango_layout_set_text(layout, textString.c_str(), (int)textString.length());
    pango_layout_set_alignment(layout, _alignment);
    pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);

    const Size maxTextureSize(bounds, 1024);
    pango_layout_set_width(layout, pango_units_from_double(maxTextureSize.width));
    pango_layout_set_height(layout, pango_units_from_double(maxTextureSize.height));
    pango_layout_set_font_description(layout, font);
    applyLeading(cairoContext, layout, font);

    PangoRectangle estimateSize;
    PangoRectangle ink;
    pango_layout_get_pixel_extents(layout, &ink, &estimateSize);

    // If the text is right or center aligned the offsets will contain all the
    // leading space.  We ignore that for the size because drawText will draw
    // in the larger box.  The tight box below will get the offsets so we know
    // where to draw so the text lands in the same tight box.
    Size res(estimateSize.width, estimateSize.height);

    if (tight != NULL) {
        float lineHeight;
        float xHeight = charHeight(cairoContext, font, 'x', &lineHeight);
        if (lineHeightOut != NULL) {
            *lineHeightOut = lineHeight;
        }
        const float capHeight = charHeight(cairoContext, font, 'Y');
        const float ascender = pango_units_to_double(pango_layout_get_baseline(layout));
        const float topSpace = ascender - capHeight;
        const float bottomSpace = MAX(lineHeight - ascender - (capHeight - xHeight), 0);
        if (res.height > topSpace + bottomSpace) {
            *tight = Rect(estimateSize.x,
                          estimateSize.y + topSpace,
                          res.width,
                          res.height - topSpace - bottomSpace);
        } else {
            *tight = Rect(0, 0, res.width, res.height);
        }
    }
    g_object_unref(layout);

    return res;
}
Пример #2
0
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
		int *baseline, double scale, bool markup, const char *fmt, ...) {
	va_list args;
	va_start(args, fmt);
	// Add one since vsnprintf excludes null terminator.
	int length = vsnprintf(NULL, 0, fmt, args) + 1;
	va_end(args);

	char *buf = malloc(length);
	if (buf == NULL) {
		sway_log(SWAY_ERROR, "Failed to allocate memory");
		return;
	}
	va_start(args, fmt);
	vsnprintf(buf, length, fmt, args);
	va_end(args);

	PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup);
	pango_cairo_update_layout(cairo, layout);
	pango_layout_get_pixel_size(layout, width, height);
	if (baseline) {
		*baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
	}
	g_object_unref(layout);
	free(buf);
}
Пример #3
0
void gtk_glwidget_create_font(){
	PangoFontDescription *font_desc;
	PangoLayout *layout;
	PangoRectangle log_rect;
	int font_ascent_pango_units;
	int font_descent_pango_units;

	if ( _debug_font_created ) {
		Error( "Programming error: gtk_glwidget_create_font() was already called; "
			   "you must call gtk_glwidget_destroy_font() before creating font again" );
	}
	_debug_font_created = 1;

	font_map = pango_ft2_font_map_new();
	pango_ft2_font_map_set_resolution( PANGO_FT2_FONT_MAP( font_map ), 72, 72 );
	ft2_context = pango_font_map_create_context( PANGO_FONT_MAP( font_map ));

	font_desc = pango_font_description_from_string( font_string );
	pango_font_description_set_size( font_desc, font_height * PANGO_SCALE );
	pango_context_set_font_description( ft2_context, font_desc );
	pango_font_description_free( font_desc );

	layout = pango_layout_new( ft2_context );

	// I don't believe that's standard preprocessor syntax?
#if !PANGO_VERSION_CHECK( 1,22,0 )
	PangoLayoutIter *iter;
	iter = pango_layout_get_iter( layout );
	font_ascent_pango_units = pango_layout_iter_get_baseline( iter );
	pango_layout_iter_free( iter );
#else
	font_ascent_pango_units = pango_layout_get_baseline( layout );
#endif

	pango_layout_get_extents( layout, NULL, &log_rect );
	g_object_unref( G_OBJECT( layout ) );
	font_descent_pango_units = log_rect.height - font_ascent_pango_units;

	font_ascent = PANGO_PIXELS_CEIL( font_ascent_pango_units );
	font_descent = PANGO_PIXELS_CEIL( font_descent_pango_units );
	y_offset_bitmap_render_pango_units = ( font_ascent * PANGO_SCALE ) - font_ascent_pango_units;
}
static int
get_pango_vertical_offset (PangoLayout *layout)
{
	const PangoFontDescription *desc;
	PangoContext               *context;
	PangoLanguage              *language;
	PangoFontMetrics           *metrics;
	int                         baseline;
	int                         strikethrough;
	int                         thickness;

	context = pango_layout_get_context (layout);
	language = pango_language_get_default ();
	desc = pango_layout_get_font_description (layout);
	metrics = pango_context_get_metrics (context, desc, language);

	baseline = pango_layout_get_baseline (layout);
	strikethrough =  pango_font_metrics_get_strikethrough_position (metrics);
	thickness =  pango_font_metrics_get_underline_thickness (metrics);

	return PANGO_PIXELS (baseline - strikethrough - thickness / 2);
}
Пример #5
0
void render_glyph(
	cairo_t* cr,
	PangoFontDescription* font_desc,
	PangoFont* font,
	const guint code_point,
	const size_t cell_x,
	const size_t cell_y,
	const size_t cell_size,
	const double tex_size,
	const int ascent,
	const int descent,
	std::ostream& bgm_out
)
{
	PangoLayout *layout = pango_cairo_create_layout(cr);

	char str[6] = {'\0'};
	size_t len = 0;
	oglplus::aux::ConvertCodePointToUTF8(code_point, str, len);

	pango_layout_set_font_description(layout, font_desc);
	pango_layout_set_text(layout, str, len);

	const int baseline = pango_layout_get_baseline(layout);
	const double inv_ps = 1.0 / double(PANGO_SCALE);
	const double font_size = ascent+descent;

	PangoRectangle ink_rect, log_rect;
	pango_layout_get_extents(
		layout,
		&ink_rect,
		&log_rect
	);

	// code point number
	bgm_out << code_point << std::endl;
	// hex representation of the number
	bgm_out	<< std::hex
		<< "0x"
		<< code_point
		<< std::dec
		<< std::endl;
	// the utf-8 sequence
	bgm_out << "'" << str << "'" << std::endl;
	//
	// vertex[0] logical rectangle metrics
	//
	// Left bearing (x)
	bgm_out << PANGO_LBEARING(log_rect)/font_size << std::endl;
	// Right bearing (x+width)
	bgm_out << PANGO_RBEARING(log_rect)/font_size << std::endl;
	// Ascent
	bgm_out << (baseline-log_rect.y)/font_size << std::endl;
	// Descent
	bgm_out << (log_rect.height+log_rect.y-baseline)/font_size << std::endl;
	//
	// vertex[1] ink rectangle metrics
	//
	// Left bearing (x)
	bgm_out << PANGO_LBEARING(ink_rect)/font_size << std::endl;
	// Right bearing (x+width)
	bgm_out << PANGO_RBEARING(ink_rect)/font_size << std::endl;
	// Ascent
	bgm_out << (baseline-ink_rect.y)/font_size << std::endl;
	// Descent
	bgm_out << (ink_rect.y+ink_rect.height-baseline)/font_size << std::endl;
	//
	// vertex[2] texture coordinates
	//
	// Origin X
	bgm_out << (cell_x*cell_size+ink_rect.x*inv_ps)/tex_size << std::endl;
	// Origin Y
	bgm_out << 1.0-(cell_y*cell_size+baseline*inv_ps)/tex_size << std::endl;
	// Width
	bgm_out << ((ink_rect.width)*inv_ps)/tex_size << std::endl;
	// Height
	bgm_out << ((ink_rect.height)*inv_ps)/tex_size << std::endl;


	// separating newline
	bgm_out << std::endl;

	cairo_new_path(cr);
	cairo_move_to(cr, cell_x*cell_size, cell_y*cell_size);
	cairo_set_line_width(cr, 0.5);

	pango_cairo_update_layout(cr, layout);
	pango_cairo_layout_path(cr, layout);
	cairo_fill(cr);

	g_object_unref(layout);
}
Пример #6
0
static void
schgui_cairo_drafter_draw_text(SchGUICairoDrafter *drafter, const struct _SchText *text)
{
    if (text != NULL)
    {
        int visible;

        sch_text_get_visible(text, &visible);

        if (visible)
        {

    SchGUICairoDrafterPrivate *privat = SCHGUI_CAIRO_DRAFTER_GET_PRIVATE(drafter);

    if (privat->cairo != NULL)
    {
        PangoLayout *layout;
        SchMultiline *multiline = sch_text_get_multiline(text);
        int point_size = sch_text_get_size(text);
        float height;
        int alignment;
        cairo_font_options_t *options;
        PangoContext *context;
        int baseline;
        PangoLayoutIter *iter;
        int index;
        int show;
        SchGUIDrawingCfgColor color;
        int          enabled;

        sch_text_get_color(text, &index);

        enabled = schgui_drawing_cfg_get_color(privat->config, index, &color);

        if (enabled)
        {
            if (0) /* show ink rect */
            {
                GeomBounds bounds;
                int        success;

                success = schgui_cairo_drafter_text_bounds(drafter, text, &bounds);

                if (success)
                {
                    cairo_set_source_rgb(privat->cairo, 1.0, 0, 0);
                
                    cairo_move_to(privat->cairo, bounds.min_x, bounds.min_y);
                    cairo_line_to(privat->cairo, bounds.max_x, bounds.min_y);
                
                    cairo_stroke(privat->cairo);

                    cairo_set_source_rgb(privat->cairo, 0.75, 0, 0);
                
                    cairo_move_to(privat->cairo, bounds.max_x, bounds.min_y);
                    cairo_line_to(privat->cairo, bounds.max_x, bounds.max_y);
                    cairo_line_to(privat->cairo, bounds.min_x, bounds.max_y);
                    cairo_line_to(privat->cairo, bounds.min_x, bounds.min_y);
                    //cairo_close_path(privat->cairo);

                    cairo_stroke(privat->cairo);
                
                    cairo_set_source_rgb(privat->cairo, 0, 0, 0);
                }

                cairo_set_source_rgb(privat->cairo, 0, 0, 1.0);
                cairo_new_sub_path(privat->cairo);
                cairo_arc(privat->cairo, sch_text_get_x(text), sch_text_get_y(text), 10, 0, 2 * M_PI);
                cairo_stroke(privat->cairo);
                cairo_set_source_rgb(privat->cairo, 0, 0, 0);
            }

            cairo_save(privat->cairo);
   
            height = 1000 * point_size / 72;

            layout = pango_cairo_create_layout(privat->cairo);
            pango_cairo_context_set_resolution(pango_layout_get_context(layout), 936);

//  context = pango_layout_get_context(layout);
//  options = cairo_font_options_create ();
//  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
//  cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_MEDIUM);
//  pango_cairo_context_set_font_options (context, options);
//  cairo_font_options_destroy (options);


            cairo_set_source_rgb(privat->cairo, color.red, color.green, color.blue);


            pango_font_description_set_size(privat->desc, point_size * PANGO_SCALE );
            pango_layout_set_spacing(layout, 40000);
        
            pango_layout_set_font_description(layout, privat->desc);

            sch_text_get_show(text, &show);
            pango_layout_set_markup(layout, sch_multiline_peek_markup(multiline, show), -1);


            PangoFontMetrics *metrics = pango_context_get_metrics(
                pango_layout_get_context(layout),
                privat->desc,
                NULL
                );

        
            cairo_move_to(privat->cairo, sch_text_get_x(text), sch_text_get_y(text));
        
            cairo_rotate(privat->cairo, M_PI * sch_text_get_angle(text) / 180);

            cairo_scale(privat->cairo, 1, -1);

            baseline = pango_layout_get_baseline(layout); 

            alignment = sch_text_get_alignment(text);
#if 1
            switch (alignment)
            {
                case 2:
                case 5:
                case 8: 
                /* upper */
                //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics)/(privat->zoom * PANGO_SCALE));
                //cairo_rel_move_to(privat->cairo, 0, height);
                break;

                case 1:
                case 4:
                case 7:
                    /* center */
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics)/(privat->zoom * PANGO_SCALE));
                    cairo_rel_move_to(privat->cairo, 0, height);
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics) * sch_multiline_lines(multiline)/(2 * privat->zoom * PANGO_SCALE));
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_descent(metrics) * (sch_multiline_lines(multiline) - 1)/(2 * privat->zoom * PANGO_SCALE));
                    break;

                case 0:
                case 3:
                case 6:
                default:
                    /* lower */
                    //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics) * sch_multiline_lines(multiline)/(privat->zoom * PANGO_SCALE));
                    //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_descent(metrics) * (sch_multiline_lines(multiline)-1)/(privat->zoom * PANGO_SCALE));
                    //cairo_rel_move_to(privat->cairo, 0, -pango_layout_get_spacing(layout) * (sch_multiline_lines(multiline)-1)/ PANGO_SCALE);
                    iter = pango_layout_get_iter(layout);
                    while (!pango_layout_iter_at_last_line(iter))
                    {
                        pango_layout_iter_next_line(iter);
                    }
                    cairo_rel_move_to(privat->cairo, 0, -pango_layout_iter_get_baseline(iter) / PANGO_SCALE);
                    pango_layout_iter_free(iter);
            }
#endif

            //g_debug("Ascent:    %d", pango_font_metrics_get_ascent(metrics));
            //g_debug("Descent:   %d", pango_font_metrics_get_descent(metrics));
            //g_debug("Spacing:   %d", pango_layout_get_spacing(layout));
            //g_debug("Font size: %d", pango_font_description_get_size(privat->desc));
            //g_debug("Baseline   %d", pango_layout_get_baseline(layout));            

            pango_font_metrics_unref(metrics);

            pango_cairo_show_layout(privat->cairo, layout);

            cairo_restore(privat->cairo);

            g_object_unref(layout);
        }
    }
}
}
 
}
Пример #7
0
	void Set(const char* c_str, const std::size_t size)
	{
		// create a cairo renderer
		PangoCairoHandle< ::cairo_t*> cairo(
			::cairo_create(_surface),
			::cairo_destroy
		);
		// clear the surface
		::cairo_save(cairo);
		::cairo_set_source_rgba(cairo, 0, 0, 0, 0);
		::cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
		::cairo_paint(cairo);
		::cairo_restore(cairo);

		// if the new text string is empty, quit
		if(size == 0) return;

		// create a layout
		PangoCairoHandle< ::PangoLayout*, ::gpointer> layout(
			::pango_cairo_create_layout(cairo),
			::g_object_unref
		);
		// set the text
		::pango_layout_set_text(layout, c_str, size);
		::pango_layout_set_font_description(
			layout,
			_font._essence->_font_desc
		);
		// check the required layout dimensions
		int req_width = 0;
		int req_height = 0;
		{
			::PangoRectangle ink_rect, log_rect;
			::pango_layout_get_extents(
				layout,
				&ink_rect,
				&log_rect
			);
			req_width = log_rect.width/PANGO_SCALE;
			req_height = log_rect.height/PANGO_SCALE;
			_curr_width = req_width;
		}

		// resize if necessary
		if((_width < req_width) || (_height < req_height))
		{
			_width = req_width;
			_height = req_height;
			_surface.replace(
				::cairo_image_surface_create(
					CAIRO_FORMAT_A8,
					_width,
					_height
				)
			);
			cairo.replace(::cairo_create(_surface));
			layout.replace(::pango_cairo_create_layout(cairo));
			PangoCairoDeallocateLayoutData(_parent, _data);
			PangoCairoAllocateLayoutData(
				_parent,
				_data,
				_width,
				_height
			);
		}
		int baseline = pango_layout_get_baseline(layout)/PANGO_SCALE;
		_log_coords = Vec4f(
			0.0f, // left bearing
			GLfloat(_curr_width)/GLfloat(_height), // right bearing
			GLfloat(baseline)/GLfloat(_height), // ascent
			GLfloat(_height-baseline)/GLfloat(_height) // descent
		);
		_tex_coords = Vec4f(
			0.0f, // origin x
			0.0f, // origin y
			_curr_width, // width
			_height // height
		);

		// render the text
		::cairo_new_path(cairo);
		::cairo_move_to(cairo, 0, 0);
		::cairo_set_line_width(cairo, 0.5);
		::pango_cairo_update_layout(cairo, layout);
		::pango_cairo_layout_path(cairo, layout);
		::cairo_fill(cairo);
		::cairo_surface_flush(_surface);

		// update the data
		PangoCairoInitializeLayoutData(
			_parent,
			_data,
			::cairo_image_surface_get_width(_surface),
			::cairo_image_surface_get_height(_surface),
			::cairo_image_surface_get_data(_surface)
		);
	}
Пример #8
0
static boolean pango_textlayout(textspan_t * span, char **fontpath)
{
    static char buf[1024];  /* returned in fontpath, only good until next call */
    static PangoFontMap *fontmap;
    static PangoContext *context;
    static PangoFontDescription *desc;
    static char *fontname;
    static double fontsize;
    static gv_font_map* gv_fmap;
    char *fnt, *psfnt = NULL;
    PangoLayout *layout;
    PangoRectangle logical_rect;
    cairo_font_options_t* options;
    PangoFont *font;
#ifdef ENABLE_PANGO_MARKUP
    PangoAttrList *attrs;
    GError *error = NULL;
    int flags;
#endif
    char *text;
    double textlayout_scale;
    PostscriptAlias *pA;

    if (!context) {
	fontmap = pango_cairo_font_map_new();
	gv_fmap = get_font_mapping(fontmap);
#ifdef HAVE_PANGO_FONT_MAP_CREATE_CONTEXT
	context = pango_font_map_create_context (fontmap);
#else
	context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap));
#endif
	options=cairo_font_options_create();
	cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY);
	cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL);
	cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON);
	cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR);
	pango_cairo_context_set_font_options(context, options);
	pango_cairo_context_set_resolution(context, FONT_DPI);
	cairo_font_options_destroy(options);
	g_object_unref(fontmap);
    }

    if (!fontname || strcmp(fontname, span->font->name) != 0 || fontsize != span->font->size) {
	fontname = span->font->name;
	fontsize = span->font->size;
	pango_font_description_free (desc);

	pA = span->font->postscript_alias;
	if (pA) {
	    psfnt = fnt = gv_fmap[pA->xfig_code].gv_font;
	    if(!psfnt)
		psfnt = fnt = pango_psfontResolve (pA);
	}
	else
	    fnt = fontname;

	desc = pango_font_description_from_string(fnt);
        /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */
        pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE));

        if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) {  /* -v support */
	    const char *fontclass;

	    fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font));

	    buf[0] = '\0';
	    if (psfnt) {
		strcat(buf, "(ps:pango  ");
		strcat(buf, psfnt);
		strcat(buf, ") ");
	    }
	    strcat(buf, "(");
	    strcat(buf, fontclass);
	    strcat(buf, ") ");
#ifdef HAVE_PANGO_FC_FONT_LOCK_FACE
	    if (strcmp(fontclass, "PangoCairoFcFont") == 0) {
	        FT_Face face;
	        PangoFcFont *fcfont;
	        FT_Stream stream;
	        FT_StreamDesc streamdesc;
	        fcfont = PANGO_FC_FONT(font);
	        face = pango_fc_font_lock_face(fcfont);
	        if (face) {
		    strcat(buf, "\"");
		    strcat(buf, face->family_name);
		    strcat(buf, ", ");
		    strcat(buf, face->style_name);
		    strcat(buf, "\" ");
    
		    stream = face->stream;
		    if (stream) {
			streamdesc = stream->pathname;
			if (streamdesc.pointer)
			    strcat(buf, (char*)streamdesc.pointer);
		        else
			    strcat(buf, "*no pathname available*");
		    }
		    else
			strcat(buf, "*no stream available*");
		}
	        pango_fc_font_unlock_face(fcfont);
	    }
	    else
#endif
	    {
    		PangoFontDescription *tdesc;
		char *tfont;
		
	        tdesc = pango_font_describe(font);
	        tfont = pango_font_description_to_string(tdesc);
	        strcat(buf, "\"");
	        strcat(buf, tfont);
	        strcat(buf, "\" ");
	        g_free(tfont);
	    }
            *fontpath = buf;
        }
    }

#ifdef ENABLE_PANGO_MARKUP
    if ((span->font) && (flags = span->font->flags)) {
	unsigned char buf[BUFSIZ];
	agxbuf xb;

	agxbinit(&xb, BUFSIZ, buf);
	agxbput(&xb,"<span");

	if (flags & HTML_BF)
	    agxbput(&xb," weight=\"bold\"");
	if (flags & HTML_IF)
	    agxbput(&xb," style=\"italic\"");
	if (flags & HTML_UL)
	    agxbput(&xb," underline=\"single\"");
	if (flags & HTML_S)
	    agxbput(&xb," strikethrough=\"true\"");
	agxbput (&xb,">");

	if (flags & HTML_SUP)
	    agxbput(&xb,"<sup>");
	if (flags & HTML_SUB)
	    agxbput(&xb,"<sub>");

	agxbput (&xb,xml_string0(span->str, TRUE));

	if (flags & HTML_SUB)
	    agxbput(&xb,"</sub>");
	if (flags & HTML_SUP)
	    agxbput(&xb,"</sup>");

	agxbput (&xb,"</span>");
	if (!pango_parse_markup (agxbuse(&xb), -1, 0, &attrs, &text, NULL, &error)) {
	    fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message);
	    text = span->str;
	    attrs = NULL;
	}
	agxbfree (&xb);
    }
    else {
	text = span->str;
	attrs = NULL;
    }
#else
    text = span->str;
#endif

    layout = pango_layout_new (context);
    span->layout = (void *)layout;    /* layout free with textspan - see labels.c */
    span->free_layout = pango_free_layout;    /* function for freeing pango layout */

    pango_layout_set_text (layout, text, -1);
    pango_layout_set_font_description (layout, desc);
#ifdef ENABLE_PANGO_MARKUP
    if (attrs)
	pango_layout_set_attributes (layout, attrs);
#endif

    pango_layout_get_extents (layout, NULL, &logical_rect);

    /* if pango doesn't like the font then it sets width=0 but height = garbage */
    if (logical_rect.width == 0)
	logical_rect.height = 0;

    textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE);
    span->size.x = (int)(logical_rect.width * textlayout_scale + 1);    /* round up so that width/height are never too small */
    span->size.y = (int)(logical_rect.height * textlayout_scale + 1);

    /* FIXME  -- Horrible kluge !!! */

    /* For now we are using pango for single line blocks only.
     * The logical_rect.height seems to be too high from the font metrics on some platforms.
     * Use an assumed height based on the point size.
     */

    span->size.y = (int)(span->font->size * 1.1 + .5);

    /* The y offset from baseline to 0,0 of the bitmap representation */
#if !defined(WIN32) && defined PANGO_VERSION_MAJOR && (PANGO_VERSION_MAJOR >= 1)
    span->yoffset_layout = pango_layout_get_baseline (layout) * textlayout_scale;
#else
    {
	/* do it the hard way on rhel5/centos5 */
	PangoLayoutIter *iter = pango_layout_get_iter (layout);
	span->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale;
    }
#endif

    /* The distance below midline for y centering of text strings */
    span->yoffset_centerline = 0.2 * span->font->size;

    if (logical_rect.width == 0)
	return FALSE;
    return TRUE;
}
Пример #9
0
 void text_rsrc::updatePixels()
 {
     scoped_lock< mutex > slock( text_mutex );
     
     text_update_context context;
     
     // Set up Cairo then Pango with initial values /////////////////////////////////////////////////////////////////////////////////////////////////////////
     
     if( max_dimensions[ 0 ] < 0 )
         dimensions[ 0 ] = PANGOCAIRO_INITIAL_PX_WIDTH;
     else
         dimensions[ 0 ] = max_dimensions[ 0 ];
     if( max_dimensions[ 1 ] < 0 )
         dimensions[ 1 ] = PANGOCAIRO_INITIAL_PX_HEIGHT;
     else
         dimensions[ 1 ] = max_dimensions[ 1 ];
     
     updatePixels_setup( &context );
     
     // Redo everything if we need to resize ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
     if( max_dimensions[ 0 ] < 0
         || max_dimensions[ 1 ] < 0 )
     {
         // Get Pango pixel dimensions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         
         PangoRectangle p_layout_inkrect;
         
         pango_layout_get_extents( context.p_layout,
                                   &p_layout_inkrect,
                                   NULL );
         
         // Make sure we have enough room
         dimensions[ 0 ] = ceil( ( double )( p_layout_inkrect.width + p_layout_inkrect.x ) / PANGO_SCALE );
         dimensions[ 1 ] = ceil( ( double )( p_layout_inkrect.height + p_layout_inkrect.y ) / PANGO_SCALE );
         
         // Clean up Pango then Cairo ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         
         updatePixels_cleanup( &context );
         
         // Re-set up Cairo then Pango with actual values ///////////////////////////////////////////////////////////////////////////////////////////////////
         
         updatePixels_setup( &context );
     }
     
     // Draw text to surface ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
     pango_cairo_show_layout( context.c_context,
                              context.p_layout );                            // Render text
     
     tex_offset[ 0 ] = 0;
     tex_offset[ 1 ] = pango_layout_get_baseline( context.p_layout ) / PANGO_SCALE * -1;
     
     // Convert Cairo surface to RGBA for OpenGL ////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
     if( pixel_space != NULL )
         delete[] pixel_space;
     
     pixel_space = new unsigned char[ dimensions[ 0 ] * dimensions [ 1 ] * 4 ];
     
     if( pixel_space == NULL )
         throw exception( "text_rsrc::updatePixels(): Could not allocate pixel space" );
     
     unsigned char* c_data = cairo_image_surface_get_data( context.c_surf );
     
     int c_stride = cairo_image_surface_get_stride( context.c_surf );
     unsigned char* c_pixelp;
     
     for( long i = 0; i < dimensions[ 0 ] * dimensions[ 1 ]; ++i )
     {
         if( i % dimensions[ 0 ] == 0 )
             c_pixelp = c_data + c_stride * ( i / dimensions[ 0 ] );         // Important since the surface stride might be wider than the surface width
         
         pixel_space[ i * 4 + 0 ] = 0xFF;
         pixel_space[ i * 4 + 1 ] = 0xFF;
         pixel_space[ i * 4 + 2 ] = 0xFF;
         pixel_space[ i * 4 + 3 ] = c_pixelp[ i % dimensions[ 0 ] ];
     }
     
     // Clean up Pango then Cairo ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
     updatePixels_cleanup( &context );
 }
Пример #10
0
static void texbox_update ( textbox *tb )
{
    if ( tb->update ) {
        unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0;
        if ( tb->main_surface ) {
            cairo_destroy ( tb->main_draw );
            cairo_surface_destroy ( tb->main_surface );
            tb->main_draw    = NULL;
            tb->main_surface = NULL;
        }
        tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h );
        tb->main_draw    = cairo_create ( tb->main_surface );
        cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );

        pango_cairo_update_layout ( tb->main_draw, tb->layout );
        int font_height = textbox_get_font_height ( tb );

        int cursor_x      = 0;
        int cursor_y      = 0;
        int cursor_width  = 2; //MAX ( 2, font_height / 10 );
        int cursor_height = font_height;

        if ( tb->changed ) {
            __textbox_update_pango_text ( tb );
        }

        if ( tb->flags & TB_EDITABLE ) {
            // We want to place the cursor based on the text shown.
            const char     *text = pango_layout_get_text ( tb->layout );
            // Clamp the position, should not be needed, but we are paranoid.
            int            cursor_offset = MIN ( tb->cursor, g_utf8_strlen ( text, -1 ) );
            PangoRectangle pos;
            // convert to byte location.
            char           *offset = g_utf8_offset_to_pointer ( text, cursor_offset );
            pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL );
            cursor_x      = pos.x / PANGO_SCALE;
            cursor_y      = pos.y / PANGO_SCALE;
            cursor_height = pos.height / PANGO_SCALE;
        }

        // Skip the side MARGIN on the X axis.
        int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset;
        int y = 0;

        if ( tb->flags & TB_RIGHT ) {
            int line_width = 0;
            // Get actual width.
            pango_layout_get_pixel_size ( tb->layout, &line_width, NULL );
            x = ( tb->widget.w - line_width - widget_padding_get_right ( WIDGET ( tb ) ) - offset );
        }
        else if ( tb->flags & TB_CENTER ) {
            int tw = textbox_get_font_width ( tb );
            x = (  ( tb->widget.w - tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) ) / 2;
        }
        y = widget_padding_get_top ( WIDGET ( tb ) ) + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE;

        rofi_theme_get_color ( WIDGET ( tb ), "foreground", tb->main_draw );
        // Text
        rofi_theme_get_color ( WIDGET ( tb ), "text", tb->main_draw );
        // draw the cursor
        if ( tb->flags & TB_EDITABLE && tb->blink ) {
            cairo_rectangle ( tb->main_draw, x + cursor_x, y + cursor_y, cursor_width, cursor_height );
            cairo_fill ( tb->main_draw );
        }

        // Set ARGB
        // We need to set over, otherwise subpixel hinting wont work.
        //cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER );
        cairo_move_to ( tb->main_draw, x, y );
        pango_cairo_show_layout ( tb->main_draw, tb->layout );

        if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) {
            cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI );
            cairo_fill ( tb->main_draw );
        }

        tb->update = FALSE;
    }
}
Пример #11
0
void wxSVGCanvasTextCairo::InitText(const wxString& text, const wxCSSStyleDeclaration& style, wxSVGMatrix* matrix) {
	BeginChar(matrix);
	
	// create path from text
	cairo_t* cr = ((wxSVGCanvasPathCairo*) m_char->path)->GetCr();
	
#if defined(__WXMSW__) || defined(__WXMAC__)
	int size = (int) style.GetFontSize();
	int fstyle = style.GetFontStyle() == wxCSS_VALUE_ITALIC ? wxFONTSTYLE_ITALIC
			: (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? wxFONTSTYLE_SLANT : wxFONTSTYLE_NORMAL);
	wxFontWeight weight = style.GetFontWeight() == wxCSS_VALUE_BOLD ? wxFONTWEIGHT_BOLD
			: style.GetFontWeight() == wxCSS_VALUE_BOLDER ? wxFONTWEIGHT_MAX
			: style.GetFontWeight() == wxCSS_VALUE_LIGHTER ? wxFONTWEIGHT_LIGHT : wxFONTWEIGHT_NORMAL;
	wxFont fnt(size, wxFONTFAMILY_DEFAULT, fstyle, weight, false, style.GetFontFamily());
#ifdef __WXMSW__
	HFONT hfont = (HFONT) fnt.GetResourceHandle();
	cairo_set_font_face(cr, cairo_win32_font_face_create_for_hfont(hfont));
#else
	CGFontRef cgFont = fnt.OSXGetCGFont();
	cairo_set_font_face(cr, cairo_quartz_font_face_create_for_cgfont(cgFont));
#endif	
	cairo_set_font_size(cr, style.GetFontSize());
	
	cairo_font_extents_t fextents;
	cairo_font_extents(cr, &fextents);
	
	double maxWidth = 0;
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxStringTokenizer tokenzr(text, wxT("\n"));
		while (tokenzr.HasMoreTokens()) {
			wxString token = tokenzr.GetNextToken();
			cairo_text_extents_t extents;
			cairo_text_extents(cr, (const char*) token.utf8_str(), &extents);
			if (maxWidth < extents.width)
				maxWidth = extents.width;
		}
	}
	
	wxStringTokenizer tokenzr(text, wxT("\n"));
	double x_advance = 0;
	double width = 0;
	double height = 0;
	double y = 0;
	while (tokenzr.HasMoreTokens()) {
		wxString token = tokenzr.GetNextToken();
		
		// get text extents
		cairo_text_extents_t extents;
		cairo_text_extents(cr, (const char*) token.utf8_str(), &extents);
		double x = style.GetTextAnchor() == wxCSS_VALUE_END ? maxWidth - extents.width
				: style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? (maxWidth - extents.width) / 2 : 0;
		
		m_char->path->MoveTo(m_tx + x, m_ty + y);
		cairo_text_path(cr, (const char*) token.utf8_str());
		
		if (x_advance < extents.x_advance)
			x_advance = extents.x_advance;
		if (width < extents.width)
			width = extents.width;
		height += fextents.height;
		if (tokenzr.HasMoreTokens())
			y += fextents.height;
	}
	
	// set bbox
	m_char->bbox = wxSVGRect(m_tx, m_ty, width, height);
	
	// increase current position (m_tx)
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxSVGRect bbox = m_char->path->GetResultBBox(style);
		m_tx += x_advance > bbox.GetWidth() ? x_advance : bbox.GetWidth();
	} else
		m_tx += x_advance;
#else
	PangoLayout* layout = pango_cairo_create_layout(cr);
	PangoFontDescription* font = pango_font_description_new();
	pango_font_description_set_family(font, style.GetFontFamily().ToAscii());
	pango_font_description_set_weight(font, style.GetFontWeight() == wxCSS_VALUE_BOLD ? PANGO_WEIGHT_BOLD
			: PANGO_WEIGHT_NORMAL);
	pango_font_description_set_style(font, style.GetFontStyle() == wxCSS_VALUE_ITALIC ? PANGO_STYLE_ITALIC
			: (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL));
	pango_font_description_set_absolute_size(font, style.GetFontSize() * PANGO_SCALE);

	PangoContext* ctx = pango_layout_get_context(layout);
	PangoFont* f = pango_context_load_font(ctx, font);
	if (f == NULL)
		pango_font_description_set_style(font, PANGO_STYLE_NORMAL);
	pango_layout_set_font_description(layout, font);
	
	if (style.GetTextAnchor() != wxCSS_VALUE_START)
		pango_layout_set_alignment(layout, style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? PANGO_ALIGN_CENTER : PANGO_ALIGN_RIGHT);
	pango_layout_set_text(layout, (const char*) text.utf8_str(), -1);
	
	int baseline = pango_layout_get_baseline(layout);
	m_char->path->MoveTo(m_tx, m_ty - ((double)baseline / PANGO_SCALE));
	pango_cairo_layout_path(cr, layout);
	
	// set bbox and increase current position (m_tx)
	int lwidth, lheight;
	pango_layout_get_size(layout, &lwidth, &lheight);
	double width = ((double)lwidth / PANGO_SCALE);
	double height = ((double)lheight / PANGO_SCALE);
	m_char->bbox = wxSVGRect(m_tx, m_ty, width, height);
	if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) {
		wxSVGRect bbox = m_char->path->GetResultBBox(style);
		m_tx += width > bbox.GetWidth() ? width : bbox.GetWidth();
	} else
		m_tx += width;
		
	g_object_unref(layout);
	pango_font_description_free(font);
#endif
}