citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

gl_buffer.cc (3836B)


      1 /*
      2  * Copyright 2012 Google, Inc. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  * Google Author(s): Behdad Esfahbod
     17  */
     18 
     19 #include "gl_buffer.h"
     20 
     21 
     22 citrun::gl_buffer::gl_buffer() : m_refcount(1), m_cursor({0, 0})
     23 {
     24 	glGenBuffers(1, &m_buf_name);
     25 	clear();
     26 }
     27 
     28 #if 0
     29 gl_buffer::~gl_buffer()
     30 {
     31 	//if (!buffer || --buffer->refcount)
     32 	//	return;
     33 
     34 	glDeleteBuffers(1, &m_buf_name);
     35 }
     36 #endif
     37 
     38 void
     39 citrun::gl_buffer::reference()
     40 {
     41 	m_refcount++;
     42 }
     43 
     44 void
     45 citrun::gl_buffer::clear()
     46 {
     47 	m_vertices.clear();
     48 	glyphy_extents_clear(&m_ink_extents);
     49 	glyphy_extents_clear(&m_logical_extents);
     50 	m_dirty = true;
     51 }
     52 
     53 void
     54 citrun::gl_buffer::extents(glyphy_extents_t *ink, glyphy_extents_t *logical)
     55 {
     56 	if (ink)
     57 		*ink = m_ink_extents;
     58 	if (logical)
     59 		*logical = m_logical_extents;
     60 }
     61 
     62 void
     63 citrun::gl_buffer::move_to(const glyphy_point_t *p)
     64 {
     65 	m_cursor = *p;
     66 }
     67 
     68 void
     69 citrun::gl_buffer::current_point(glyphy_point_t *p)
     70 {
     71 	*p = m_cursor;
     72 }
     73 
     74 void
     75 citrun::gl_buffer::add_text(const char *utf8, citrun::gl_font &font, double font_size)
     76 {
     77 	FT_Face face = font.get_face();
     78 	glyphy_point_t top_left = m_cursor;
     79 	m_cursor.y += font_size /* * font->ascent */;
     80 	unsigned int unicode;
     81 	unsigned int col = 0;
     82 
     83 	for (const unsigned char *p = (const unsigned char *) utf8; *p; p++) {
     84 		if (*p < 128) {
     85 			unicode = *p;
     86 		} else {
     87 			unsigned int j;
     88 			if (*p < 0xE0) {
     89 				unicode = *p & ~0xE0;
     90 				j = 1;
     91 			} else if (*p < 0xF0) {
     92 				unicode = *p & ~0xF0;
     93 				j = 2;
     94 			} else {
     95 				unicode = *p & ~0xF8;
     96 				j = 3;
     97 				continue;
     98 			}
     99 			p++;
    100 			for (; j && *p; j--, p++)
    101 				unicode = (unicode << 6) | (*p & ~0xC0);
    102 			p--;
    103 		}
    104 
    105 		if (unicode == '\n') {
    106 			m_cursor.y += font_size;
    107 			m_cursor.x = top_left.x;
    108 			col = 0;
    109 			continue;
    110 		}
    111 
    112 		unsigned int glyph_index = FT_Get_Char_Index(face, unicode);
    113 		glyph_info_t gi;
    114 		font.lookup_glyph(glyph_index, &gi);
    115 
    116 		/* Let tab operate like it does in editors, 8 spaces. */
    117 		if (unicode == '\t') {
    118 			int nspaces = 8 - (col % 8);
    119 			m_cursor.x += font_size * gi.advance * nspaces;
    120 			col += nspaces;
    121 			continue;
    122 		}
    123 
    124 		/* Update ink extents */
    125 		glyphy_extents_t m_ink_extents;
    126 		shader.add_glyph_vertices(m_cursor, font_size, &gi, &m_vertices, &m_ink_extents);
    127 		glyphy_extents_extend(&m_ink_extents, &m_ink_extents);
    128 
    129 		/* Update logical extents */
    130 		glyphy_point_t corner;
    131 		corner.x = m_cursor.x;
    132 		corner.y = m_cursor.y - font_size;
    133 		glyphy_extents_add(&m_logical_extents, &corner);
    134 		corner.x = m_cursor.x + font_size * gi.advance;
    135 		corner.y = m_cursor.y;
    136 		glyphy_extents_add(&m_logical_extents, &corner);
    137 
    138 		m_cursor.x += font_size * gi.advance;
    139 
    140 		/* Hack; Not all characters are a single column wide. */
    141 		col++;
    142 	}
    143 
    144 	m_dirty = true;
    145 }
    146 
    147 void
    148 citrun::gl_buffer::draw()
    149 {
    150 	GLint program;
    151 	glGetIntegerv(GL_CURRENT_PROGRAM, &program);
    152 	GLuint a_glyph_vertex_loc = glGetAttribLocation(program, "a_glyph_vertex");
    153 	glBindBuffer(GL_ARRAY_BUFFER, m_buf_name);
    154 	if (m_dirty) {
    155 		glBufferData(GL_ARRAY_BUFFER,  sizeof (glyph_vertex_t) * m_vertices.size(), (const char *) &(m_vertices)[0], GL_STATIC_DRAW);
    156 		m_dirty = false;
    157 	}
    158 	glEnableVertexAttribArray (a_glyph_vertex_loc);
    159 	glVertexAttribPointer (a_glyph_vertex_loc, 4, GL_FLOAT, GL_FALSE, sizeof (glyph_vertex_t), 0);
    160 	glDrawArrays (GL_TRIANGLES, 0, m_vertices.size());
    161 	glDisableVertexAttribArray (a_glyph_vertex_loc);
    162 }