Пример #1
0
// ----------------------------------------------------------------------------
void
text_buffer_add_wchar( text_buffer_t * self,
                       vec2 * pen, markup_t * markup,
                       wchar_t current, wchar_t previous )
{
    size_t vcount = 0;
    size_t icount = 0;
    vertex_buffer_t * buffer = self->buffer;
    texture_font_t * font = markup->font;
    float gamma = markup->gamma;

    // Maximum number of vertices is 20 (= 5x2 triangles) per glyph:
    //  - 2 triangles for background
    //  - 2 triangles for overline
    //  - 2 triangles for underline
    //  - 2 triangles for strikethrough
    //  - 2 triangles for glyph
    glyph_vertex_t vertices[4*5];
    GLuint indices[6*5];
    texture_glyph_t *glyph;
    texture_glyph_t *black;
    float kerning = 0;
   
    if( current == L'\n' )
    {
        pen->x = self->origin.x;
        pen->y += self->line_descender;
        self->line_descender = 0;
        self->line_ascender = 0;
        self->line_start = vector_size( self->buffer->items );
        return;
    }

    if( markup->font->ascender > self->line_ascender )
    {
        float y = pen->y;
        pen->y -= (markup->font->ascender - self->line_ascender);
        text_buffer_move_last_line( self, (int)(y-pen->y) );
        self->line_ascender = markup->font->ascender;
    }
    if( markup->font->descender < self->line_descender )
    {
        self->line_descender = markup->font->descender;
    }

    glyph = texture_font_get_glyph( font, current );
    black = texture_font_get_glyph( font, -1 );
        
    if( glyph == NULL )
    {
        return;
    }
    
    if( previous && markup->font->kerning )
    {
        kerning = texture_glyph_get_kerning( glyph, previous );
    }
    pen->x += kerning;
        
    // Background
    if( markup->background_color.alpha > 0 )
    {
        float r = markup->background_color.r;
        float g = markup->background_color.g;
        float b = markup->background_color.b;
        float a = markup->background_color.a;
        float x0 = ( pen->x -kerning );
        float y0 = (int)( pen->y + font->descender );
        float x1 = ( x0 + glyph->advance_x );
        float y1 = (int)( y0 + font->height + font->linegap );
        float s0 = black->s0;
        float t0 = black->t0;
        float s1 = black->s1;
        float t1 = black->t1;

        SET_GLYPH_VERTEX(vertices[vcount+0],
                         (int)x0,y0,0,  s0,t0,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+1],
                         (int)x0,y1,0,  s0,t1,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+2],
                         (int)x1,y1,0,  s1,t1,  r,g,b,a,  x1-((int)x1), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+3],
                         (int)x1,y0,0,  s1,t0,  r,g,b,a,  x1-((int)x1), gamma );
        indices[icount + 0] = vcount+0;
        indices[icount + 1] = vcount+1;
        indices[icount + 2] = vcount+2;
        indices[icount + 3] = vcount+0;
        indices[icount + 4] = vcount+2;
        indices[icount + 5] = vcount+3;
        vcount += 4;
        icount += 6;
    }
        
    // Underline
    if( markup->underline )
    {
        float r = markup->underline_color.r;
        float g = markup->underline_color.g;
        float b = markup->underline_color.b;
        float a = markup->underline_color.a;
        float x0 = ( pen->x - kerning );
        float y0 = (int)( pen->y + font->underline_position );
        float x1 = ( x0 + glyph->advance_x );
        float y1 = (int)( y0 + font->underline_thickness ); 
        float s0 = black->s0;
        float t0 = black->t0;
        float s1 = black->s1;
        float t1 = black->t1;

        SET_GLYPH_VERTEX(vertices[vcount+0],
                         (int)x0,y0,0,  s0,t0,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+1],
                         (int)x0,y1,0,  s0,t1,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+2],
                         (int)x1,y1,0,  s1,t1,  r,g,b,a,  x1-((int)x1), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+3],
                         (int)x1,y0,0,  s1,t0,  r,g,b,a,  x1-((int)x1), gamma );
        indices[icount + 0] = vcount+0;
        indices[icount + 1] = vcount+1;
        indices[icount + 2] = vcount+2;
        indices[icount + 3] = vcount+0;
        indices[icount + 4] = vcount+2;
        indices[icount + 5] = vcount+3;
        vcount += 4;
        icount += 6;
    }
    
    // Overline
    if( markup->overline )
    {
        float r = markup->overline_color.r;
        float g = markup->overline_color.g;
        float b = markup->overline_color.b;
        float a = markup->overline_color.a;
        float x0 = ( pen->x -kerning );
        float y0 = (int)( pen->y + (int)font->ascender );
        float x1 = ( x0 + glyph->advance_x );
        float y1 = (int)( y0 + (int)font->underline_thickness ); 
        float s0 = black->s0;
        float t0 = black->t0;
        float s1 = black->s1;
        float t1 = black->t1;
        SET_GLYPH_VERTEX(vertices[vcount+0],
                         (int)x0,y0,0,  s0,t0,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+1],
                         (int)x0,y1,0,  s0,t1,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+2],
                         (int)x1,y1,0,  s1,t1,  r,g,b,a,  x1-((int)x1), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+3],
                         (int)x1,y0,0,  s1,t0,  r,g,b,a,  x1-((int)x1), gamma );
        indices[icount + 0] = vcount+0;
        indices[icount + 1] = vcount+1;
        indices[icount + 2] = vcount+2;
        indices[icount + 3] = vcount+0;
        indices[icount + 4] = vcount+2;
        indices[icount + 5] = vcount+3;
        vcount += 4;
        icount += 6;
    }
        
    /* Strikethrough */
    if( markup->strikethrough )
    {
        float r = markup->strikethrough_color.r;
        float g = markup->strikethrough_color.g;
        float b = markup->strikethrough_color.b;
        float a = markup->strikethrough_color.a;
        float x0  = ( pen->x -kerning );
        float y0  = (int)( pen->y + (int)font->ascender*.33);
        float x1  = ( x0 + glyph->advance_x );
        float y1  = (int)( y0 + (int)font->underline_thickness ); 
        float s0 = black->s0;
        float t0 = black->t0;
        float s1 = black->s1;
        float t1 = black->t1;
        SET_GLYPH_VERTEX(vertices[vcount+0],
                         (int)x0,y0,0,  s0,t0,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+1],
                         (int)x0,y1,0,  s0,t1,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+2],
                         (int)x1,y1,0,  s1,t1,  r,g,b,a,  x1-((int)x1), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+3],
                         (int)x1,y0,0,  s1,t0,  r,g,b,a,  x1-((int)x1), gamma );
        indices[icount + 0] = vcount+0;
        indices[icount + 1] = vcount+1;
        indices[icount + 2] = vcount+2;
        indices[icount + 3] = vcount+0;
        indices[icount + 4] = vcount+2;
        indices[icount + 5] = vcount+3;
        vcount += 4;
        icount += 6;
    }
    {
        // Actual glyph
        float r = markup->foreground_color.red;
        float g = markup->foreground_color.green;
        float b = markup->foreground_color.blue;
        float a = markup->foreground_color.alpha;
        float x0 = ( pen->x + glyph->offset_x );
        float y0 = (int)( pen->y + glyph->offset_y );
        float x1 = ( x0 + glyph->width );
        float y1 = (int)( y0 - glyph->height );
        float s0 = glyph->s0;
        float t0 = glyph->t0;
        float s1 = glyph->s1;
        float t1 = glyph->t1;

        SET_GLYPH_VERTEX(vertices[vcount+0],
                         (int)x0,y0,0,  s0,t0,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+1],
                         (int)x0,y1,0,  s0,t1,  r,g,b,a,  x0-((int)x0), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+2],
                         (int)x1,y1,0,  s1,t1,  r,g,b,a,  x1-((int)x1), gamma );
        SET_GLYPH_VERTEX(vertices[vcount+3],
                         (int)x1,y0,0,  s1,t0,  r,g,b,a,  x1-((int)x1), gamma );
        indices[icount + 0] = vcount+0;
        indices[icount + 1] = vcount+1;
        indices[icount + 2] = vcount+2;
        indices[icount + 3] = vcount+0;
        indices[icount + 4] = vcount+2;
        indices[icount + 5] = vcount+3;
        vcount += 4;
        icount += 6;
    
        vertex_buffer_push_back( buffer, vertices, vcount, indices, icount );
        pen->x += glyph->advance_x * (1.0 + markup->spacing);
    }
}
Пример #2
0
int xpl_text_buffer_add_wchar(xpl_text_buffer_t *self, xvec2 *pen, xpl_markup_t *markup, wchar_t current, wchar_t previous) {
	assert(self);
	assert(pen);
	assert(markup);
	assert(current);

	// indices moved forward by this because all share the same vbo
	size_t voffset = self->vertex_count;
	size_t vcount = 0;
	size_t icount = 0;

	xpl_font_t *font = markup->font;
	float gamma = markup->gamma;

	// Maximum number of vertices is 20 (= 5x2 triangles) per glyph:
	//  - 2 triangles for background
	//  - 2 triangles for overline
	//  - 2 triangles for underline
	//  - 2 triangles for strikethrough
	//  - 2 triangles for glyph
	glyph_vertex_t vertices[4 * 5];
	GLushort indices[6 * 5]; // two shared vertices per triangle

	if (current == L'\n') {
		pen->x = self->pen_origin.x;
		if (previous == L'\n') {
			// No line descender for this line, so make something up
			pen->y -= markup->font->height * 1.1f;
		} else {
			pen->y -= self->line_descender + markup->font->height;
		}
		self->line_descender = 0.0f;
		self->line_ascender = 0.0f;
		self->line_start = self->vertex_count;
		return FALSE;
	}

	if (markup->font->ascender > self->line_ascender) {
		float y = pen->y;
        pen->y -= markup->font->ascender - self->line_ascender;
		text_buffer_move_last_line(self, (int)(y - pen->y));
		self->line_ascender = markup->font->ascender;
	}
	if (markup->font->descender < self->line_descender) {
		self->line_descender = xmin(markup->font->descender, self->line_descender);
	}

	xpl_glyph_t *glyph = xpl_font_get_glyph(font, current);
	if (! glyph) {
		LOG_WARN("Glyph %c not found", current);
		return FALSE;
	}
	xpl_glyph_t *empty = xpl_font_get_glyph(font, -1);

	float kerning = 0.0f;
	if (previous > 0) {
		kerning = xpl_font_glyph_get_kerning(glyph, previous);
		pen->x += kerning;
	}

	if (markup->background_color.alpha > 0) {
		float r = markup->background_color.r;
		float g = markup->background_color.g;
		float b = markup->background_color.b;
		float a = markup->background_color.a;
		float x0 = pen->x - kerning;
		float y0 = (float)(int)(pen->y + font->descender);
		float x1 = x0 + glyph->advance_x;
		float y1 = (float)(int)(y0 + font->height + font->linegap);
		float s0 = empty->tex_s0;
		float t0 = empty->tex_t0;
		float s1 = empty->tex_s1;
		float t1 = empty->tex_t1;

		SET_GLYPH_VERTEX(vertices[vcount + 0], (int)x0, y0, 0,  s0, t0,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 1], (int)x0, y1, 0,  s0, t1,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 2], (int)x1, y1, 0,  s1, t1,  r, g, b, a,  x1 - ((int)x1), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 3], (int)x1, y0, 0,  s1, t0,  r, g, b, a,  x1 - ((int)x1), gamma);
		indices[icount + 0] = voffset + vcount + 0;
		indices[icount + 1] = voffset + vcount + 1;
		indices[icount + 2] = voffset + vcount + 2;
		indices[icount + 3] = voffset + vcount + 0;
		indices[icount + 4] = voffset + vcount + 2;
		indices[icount + 5] = voffset + vcount + 3;
		vcount += 4;
		icount += 6;
	}

	if (markup->underline) {
		float r = markup->underline_color.r;
		float g = markup->underline_color.g;
		float b = markup->underline_color.b;
		float a = markup->underline_color.a;
		float x0 = pen->x - kerning;
		float y0 = (float)(int)(pen->y + font->underscore_position);
		float x1 = x0 + glyph->advance_x;
		float y1 = (float)(int)(y0 + font->underscore_thickness);
		float s0 = empty->tex_s0;
		float t0 = empty->tex_t0;
		float s1 = empty->tex_s1;
		float t1 = empty->tex_t1;

		SET_GLYPH_VERTEX(vertices[vcount + 0], (int)x0, y0, 0,  s0, t0,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 1], (int)x0, y1, 0,  s0, t1,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 2], (int)x1, y1, 0,  s1, t1,  r, g, b, a,  x1 - ((int)x1), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 3], (int)x1, y0, 0,  s1, t0,  r, g, b, a,  x1 - ((int)x1), gamma);

		indices[icount + 0] = voffset + vcount + 0;
		indices[icount + 1] = voffset + vcount + 1;
		indices[icount + 2] = voffset + vcount + 2;
		indices[icount + 3] = voffset + vcount + 0;
		indices[icount + 4] = voffset + vcount + 2;
		indices[icount + 5] = voffset + vcount + 3;
		vcount += 4;
		icount += 6;
	}

	if (markup->overline) {
		float r = markup->overline_color.r;
		float g = markup->overline_color.g;
		float b = markup->overline_color.b;
		float a = markup->overline_color.a;
		float x0 = pen->x - kerning;
		float y0 = (float)(int)(pen->y + (int)font->ascender);
		float x1 = x0 + glyph->advance_x;
		float y1 = (float)(int)(y0 + (int)font->underscore_thickness);
		float s0 = empty->tex_s0;
		float t0 = empty->tex_t0;
		float s1 = empty->tex_s1;
		float t1 = empty->tex_t1;

		SET_GLYPH_VERTEX(vertices[vcount + 0], (int)x0, y0, 0,  s0, t0,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 1], (int)x0, y1, 0,  s0, t1,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 2], (int)x1, y1, 0,  s1, t1,  r, g, b, a,  x1 - ((int)x1), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 3], (int)x1, y0, 0,  s1, t0,  r, g, b, a,  x1 - ((int)x1), gamma);
		indices[icount + 0] = voffset + vcount + 0;
		indices[icount + 1] = voffset + vcount + 1;
		indices[icount + 2] = voffset + vcount + 2;
		indices[icount + 3] = voffset + vcount + 0;
		indices[icount + 4] = voffset + vcount + 2;
		indices[icount + 5] = voffset + vcount + 3;
		vcount += 4;
		icount += 6;
	}

	if (markup->strikethrough) {
		float r = markup->strikethrough_color.r;
		float g = markup->strikethrough_color.g;
		float b = markup->strikethrough_color.b;
		float a = markup->strikethrough_color.a;
		float x0 = pen->x - kerning;
		float y0 = (float)(int)(pen->y + (int)(0.33f * font->ascender));
		float x1 = x0 + glyph->advance_x;
		float y1 = (float)(int)(y0 + (int)font->underscore_thickness);
		float s0 = empty->tex_s0;
		float t0 = empty->tex_t0;
		float s1 = empty->tex_s1;
		float t1 = empty->tex_t1;

		SET_GLYPH_VERTEX(vertices[vcount + 0], x0, y0, 0,  s0, t0,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 1], x0, y1, 0,  s0, t1,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 2], x1, y1, 0,  s1, t1,  r, g, b, a,  x1 - ((int)x1), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 3], x1, y0, 0,  s1, t0,  r, g, b, a,  x1 - ((int)x1), gamma);
		indices[icount + 0] = voffset + vcount + 0;
		indices[icount + 1] = voffset + vcount + 1;
		indices[icount + 2] = voffset + vcount + 2;
		indices[icount + 3] = voffset + vcount + 0;
		indices[icount + 4] = voffset + vcount + 2;
		indices[icount + 5] = voffset + vcount + 3;
		vcount += 4;
		icount += 6;
	}

	// HOOORAY, IT'S THE GLYPH!
	// Watch, I'll never use strikeline or overthrough
	{
		float r = markup->foreground_color.r;
		float g = markup->foreground_color.g;
		float b = markup->foreground_color.b;
		float a = markup->foreground_color.a;
		float x0 = pen->x + glyph->offset_x;
		float y0 = (float)(int)(pen->y + glyph->offset_y);
		float x1 = x0 + glyph->width;
		float y1 = (float)(int)(y0 - glyph->height);
		float s0 = glyph->tex_s0;
		float t0 = glyph->tex_t0;
		float s1 = glyph->tex_s1;
		float t1 = glyph->tex_t1;

		SET_GLYPH_VERTEX(vertices[vcount + 0], x0, y0, 0,  s0, t0,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 1], x0, y1, 0,  s0, t1,  r, g, b, a,  x0 - ((int)x0), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 2], x1, y1, 0,  s1, t1,  r, g, b, a,  x1 - ((int)x1), gamma);
		SET_GLYPH_VERTEX(vertices[vcount + 3], x1, y0, 0,  s1, t0,  r, g, b, a,  x1 - ((int)x1), gamma);
		indices[icount + 0] = voffset + vcount + 0;
		indices[icount + 1] = voffset + vcount + 1;
		indices[icount + 2] = voffset + vcount + 2;
		indices[icount + 3] = voffset + vcount + 0;
		indices[icount + 4] = voffset + vcount + 2;
		indices[icount + 5] = voffset + vcount + 3;
		vcount += 4;
		icount += 6;
		LOG_TRACE("Adding character %lc: (%f,%f):(%f,%f)", current, x0, y0, x1, y1);
	}

	xpl_bo_append(self->vertices, vertices, vcount * sizeof (glyph_vertex_t));
	xpl_bo_append(self->vao->index_bos[0], indices, icount * sizeof (GLushort));

#    if 0
	LOG_DEBUG("Index buffer content: ")
	GLushort *val;
	size_t elements = self->vao->index_bos[0]->client_data->length / sizeof (GLushort);
	for (size_t i = 0; i < elements; i++) {
		val = ((GLushort *)self->vao->index_bos[0]->client_data->content) + i;
		LOG_DEBUG("%hu", *val);
	}
#    endif

	self->vertex_count += vcount;
	self->index_count += icount;

	pen->x += glyph->advance_x * (1.0f + markup->spacing);

	return TRUE;
}