first commit
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGTextLayer.hxx"
|
||||
|
||||
SGPath FGTextLayer::The_Font_Path;
|
||||
|
||||
FGFontCache FGTextLayer::The_Font_Cache;
|
||||
|
||||
GLuint FGTextLayer::Text_Layer_Program_Object (0);
|
||||
GLint FGTextLayer::Text_Layer_Position_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Tex_Coord_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_MVP_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Sampler_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Color_Loc (0);
|
||||
|
||||
bool
|
||||
FGTextLayer::Init () {
|
||||
const char V_Text_Layer_Shader_Str[] =
|
||||
#ifdef _RPI
|
||||
"#version 100 \n"
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_tex_coord; \n"
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
#else
|
||||
"#version 130 \n"
|
||||
"in vec4 a_position; \n"
|
||||
"in vec2 a_tex_coord; \n"
|
||||
"out vec2 v_tex_coord; \n"
|
||||
#endif
|
||||
"uniform mat4 u_mvp_matrix; \n"
|
||||
"void main () { \n"
|
||||
" gl_Position = u_mvp_matrix * a_position; \n"
|
||||
" v_tex_coord = a_tex_coord; \n"
|
||||
"} \n";
|
||||
|
||||
const char F_Text_Layer_Shader_Str[] =
|
||||
#ifdef _RPI
|
||||
"#version 100 \n"
|
||||
"precision mediump float; \n"
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
#else
|
||||
"#version 130 \n"
|
||||
"in vec2 v_tex_coord; \n"
|
||||
#endif
|
||||
"uniform sampler2D u_texture; \n"
|
||||
"uniform vec4 u_color; \n"
|
||||
"void main () { \n"
|
||||
" gl_FragColor = vec4 (1, 1, 1, \n"
|
||||
" texture2D (u_texture, v_tex_coord).a) * \n"
|
||||
" u_color; \n"
|
||||
"} \n";
|
||||
|
||||
Text_Layer_Program_Object = GL_utils::instance ().load_program (V_Text_Layer_Shader_Str,
|
||||
F_Text_Layer_Shader_Str);
|
||||
if (Text_Layer_Program_Object == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the attribute locations
|
||||
Text_Layer_Position_Loc = glGetAttribLocation (Text_Layer_Program_Object, "a_position");
|
||||
Text_Layer_Tex_Coord_Loc = glGetAttribLocation (Text_Layer_Program_Object, "a_tex_coord");
|
||||
|
||||
// Get the uniform locations
|
||||
Text_Layer_MVP_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_mvp_matrix");
|
||||
|
||||
// Get the sampler location
|
||||
Text_Layer_Sampler_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_texture");
|
||||
|
||||
// Get the color location
|
||||
Text_Layer_Color_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_color");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FGTextLayer::FGTextLayer (const int w, const int h) :
|
||||
FGInstrumentLayer (w, h),
|
||||
m_pointSize (0.0),
|
||||
m_font_name () {
|
||||
m_then.stamp ();
|
||||
m_color[0] = m_color[1] = m_color[2] = 0.0;
|
||||
m_color[3] = 1.0;
|
||||
}
|
||||
|
||||
FGTextLayer::~FGTextLayer () {
|
||||
for (chunk_list::iterator It = m_chunks.begin ();
|
||||
It != m_chunks.end ();
|
||||
++It) {
|
||||
delete *It;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::draw () {
|
||||
if (test ()) {
|
||||
glUseProgram (Text_Layer_Program_Object);
|
||||
glUniform4fv (Text_Layer_Color_Loc, 1, m_color);
|
||||
|
||||
transform ();
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Text_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
GLuint Glyph_Texture;
|
||||
if (!The_Font_Cache.Set_Font (m_font_name, m_pointSize, Glyph_Texture)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Missing font : " << m_font_name << " " << m_pointSize);
|
||||
}
|
||||
|
||||
m_now.stamp ();
|
||||
const long diff ((m_now - m_then).toUSecs ());
|
||||
|
||||
if (diff > 100000 || diff < 0 ) {
|
||||
// ( diff < 0 ) is a sanity check and indicates our time stamp
|
||||
// difference math probably overflowed. We can handle a max
|
||||
// difference of 35.8 minutes since the returned value is in
|
||||
// usec. So if the panel is left off longer than that we can
|
||||
// over flow the math with it is turned back on. This (diff <
|
||||
// 0) catches that situation, get's us out of trouble, and
|
||||
// back on track.
|
||||
recalc_value ();
|
||||
m_then = m_now;
|
||||
}
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, Glyph_Texture);
|
||||
glUniform1i (Text_Layer_Sampler_Loc, 0);
|
||||
|
||||
int X (0);
|
||||
int Y (0);
|
||||
int Previous_X (0);
|
||||
int Previous_Y (0);
|
||||
int Left, Bottom, W, H;
|
||||
double X1, Y1, X2, Y2;
|
||||
|
||||
for (string::iterator It = m_value.begin (); It != m_value.end (); ++It) {
|
||||
if (The_Font_Cache.Get_Char (*It,
|
||||
X, Y,
|
||||
Left, Bottom,
|
||||
W, H,
|
||||
X1, Y1,
|
||||
X2, Y2)) {
|
||||
const GLfloat v_Vertices[] = {
|
||||
float (Previous_X + Left), float (Previous_Y + Bottom), 0.0f, // Position 0 (bottom left corner)
|
||||
float (X1), float (Y2), // TexCoord 0 (bottom left corner)
|
||||
float (Previous_X + Left + W), float (Previous_Y + Bottom), 0.0f, // Position 1 (bottom right corner)
|
||||
float (X2), float (Y2), // TexCoord 1 (bottom right corner)
|
||||
float (Previous_X + Left + W), float (Previous_Y + Bottom + H), 0.0f, // Position 2 (top right corner)
|
||||
float (X2), float (Y1), // TexCoord 2 (top right corner)
|
||||
float (Previous_X + Left), float (Previous_Y + Bottom + H), 0.0f, // Position 3 (top left corner)
|
||||
float (X1), float (Y1) }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Text_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices);
|
||||
glVertexAttribPointer (Text_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices[3]);
|
||||
|
||||
glEnableVertexAttribArray (Text_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Text_Layer_Tex_Coord_Loc);
|
||||
|
||||
const GLushort indices[] = {0, 1, 2, 0, 2, 3};
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
Previous_X = X;
|
||||
Previous_Y = Y;
|
||||
}
|
||||
}
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::addChunk (FGTextLayer::Chunk * const chunk) {
|
||||
m_chunks.push_back (chunk);
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setColor (const float r,
|
||||
const float g,
|
||||
const float b) {
|
||||
m_color[0] = r;
|
||||
m_color[1] = g;
|
||||
m_color[2] = b;
|
||||
m_color[3] = 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setPointSize (const float size) {
|
||||
m_pointSize = size;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setFontName (const string &name) {
|
||||
if (The_Font_Path.isNull ()) {
|
||||
char *Env_Path = ::getenv ("FG_FONTS");
|
||||
if (Env_Path != NULL) {
|
||||
The_Font_Path = SGPath::fromEnv (Env_Path);
|
||||
} else {
|
||||
The_Font_Path = ApplicationProperties::GetRootPath ("Fonts");
|
||||
}
|
||||
}
|
||||
m_font_name = The_Font_Path.local8BitStr () + "/" + name + ".ttf";
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::recalc_value () const {
|
||||
m_value = "";
|
||||
for (chunk_list::const_iterator It = m_chunks.begin ();
|
||||
It != m_chunks.end ();
|
||||
++It) {
|
||||
m_value += (*It)->getValue ();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGTextLayer::Chunk.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGTextLayer::Chunk::Chunk (const string &text,
|
||||
const string &fmt) :
|
||||
m_type (FGTextLayer::TEXT),
|
||||
m_text (text),
|
||||
m_fmt (fmt),
|
||||
m_mult (1.0),
|
||||
m_offs (0.0),
|
||||
m_trunc (false) {
|
||||
if (m_fmt.empty ()) {
|
||||
m_fmt = "%s";
|
||||
}
|
||||
}
|
||||
|
||||
FGTextLayer::Chunk::Chunk (const ChunkType type,
|
||||
const SGPropertyNode *node,
|
||||
const string &fmt,
|
||||
const float mult,
|
||||
const float offs,
|
||||
const bool truncation) :
|
||||
m_type (type),
|
||||
m_node (node),
|
||||
m_fmt (fmt),
|
||||
m_mult (mult),
|
||||
m_offs (offs),
|
||||
m_trunc (truncation) {
|
||||
if (m_fmt.empty ()) {
|
||||
if (type == TEXT_VALUE) {
|
||||
m_fmt = "%s";
|
||||
} else {
|
||||
m_fmt = "%.2f";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
FGTextLayer::Chunk::getValue () const {
|
||||
if (test ()) {
|
||||
m_buf[0] = '\0';
|
||||
switch (m_type) {
|
||||
case TEXT:
|
||||
sprintf (m_buf, m_fmt.c_str (), m_text.c_str ());
|
||||
break;
|
||||
case TEXT_VALUE:
|
||||
sprintf (m_buf, m_fmt.c_str (), m_node->getStringValue ());
|
||||
break;
|
||||
case DOUBLE_VALUE:
|
||||
double d (m_offs + m_node->getFloatValue() * m_mult);
|
||||
if (m_trunc) {
|
||||
d = (d < 0) ? -floor (-d) : floor (d);
|
||||
}
|
||||
sprintf (m_buf, m_fmt.c_str(), d);
|
||||
break;
|
||||
}
|
||||
return m_buf;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user