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 }