const char * TTF_BreakString(int w, const char *in) { TTFtextRow rows[2]; int nrows = 0, i; int oldAlign = state.align; int halign = state.align & (FONS_ALIGN_LEFT | FONS_ALIGN_CENTER | FONS_ALIGN_RIGHT); int valign = state.align & (FONS_ALIGN_TOP | FONS_ALIGN_MIDDLE | FONS_ALIGN_BOTTOM | FONS_ALIGN_BASELINE); float lineh; fonsVertMetrics(ctx, nullptr, nullptr, &lineh); fonsSetAlign(ctx, FONS_ALIGN_LEFT | valign); if (splitStr != nullptr) { sdsfree(splitStr); } splitStr = sdsempty(); while ((nrows = TTF_BreakLines(in, nullptr, w, rows, 2)) > 0) { for (i = 0; i < nrows; i++) { TTFtextRow* row = &rows[i]; splitStr = sdscatlen(splitStr, row->start, row->end - row->start); splitStr = sdscat(splitStr, "\n"); } in = rows[nrows - 1].next; } fonsSetAlign(ctx, oldAlign); return splitStr; }
void TTF_TextBox(const drawTextCommand_t *cmd, const char *string, int count) { TTFtextRow rows[2]; int nrows = 0, i; int oldAlign = state.align; int halign = state.align & (FONS_ALIGN_LEFT | FONS_ALIGN_CENTER | FONS_ALIGN_RIGHT); int valign = state.align & (FONS_ALIGN_TOP | FONS_ALIGN_MIDDLE | FONS_ALIGN_BOTTOM | FONS_ALIGN_BASELINE); float lineh; fonsPushState(ctx); fonsVertMetrics(ctx, nullptr, nullptr, &lineh); fonsSetAlign(ctx, FONS_ALIGN_LEFT | valign); float x = cmd->x; float y = cmd->y; lineh *= state.lineHeight; const char *end = TTF_CountChars(string, count); while ((nrows = TTF_BreakLines(string, end, cmd->w, rows, 2)) > 0) { for (i = 0; i < nrows; i++) { TTFtextRow* row = &rows[i]; if (halign & FONS_ALIGN_LEFT) fonsDrawText(ctx, x, y, row->start, row->end); else if (halign & FONS_ALIGN_CENTER) fonsDrawText(ctx, x + cmd->w * 0.5f - row->width*0.5f, y, row->start, row->end); else if (halign & FONS_ALIGN_RIGHT) fonsDrawText(ctx, x + cmd->w - row->width, y, row->start, row->end); y += lineh; } string = rows[nrows - 1].next; } fonsPopState(ctx); }
bool ofxFontStash2::applyStyle(const ofxFontStashStyle & style){ //if(style.fontID.size()){ fonsClearState(fs); int id = getFsID(style.fontID); fonsSetFont(fs, id); fonsSetSize(fs, style.fontSize * pixelDensity * fontScale); fonsSetColor(fs, toFScolor(style.color)); fonsSetAlign(fs, style.alignment); fonsSetBlur(fs, style.blur); return id != FONS_INVALID; //} }
void GLHelper::drawText(const std::string& text, const Position& pos, const double layer, const double size, const RGBColor& col, const double angle, const int align, double width) { if (width <= 0) { width = size; } if (!initFont()) { return; }; glPushMatrix(); glAlphaFunc(GL_GREATER, 0.5); glEnable(GL_ALPHA_TEST); glTranslated(pos.x(), pos.y(), layer); glScaled(width / myFontSize, size / myFontSize, 1.); glRotated(-angle, 0, 0, 1); fonsSetAlign(myFont, align == 0 ? FONS_ALIGN_CENTER | FONS_ALIGN_MIDDLE : align); fonsSetColor(myFont, glfonsRGBA(col.red(), col.green(), col.blue(), col.alpha())); fonsDrawText(myFont, 0., 0., text.c_str(), nullptr); glPopMatrix(); }
void LikertHCI::initializeText(int threadId, FONScontext* fs, int fontNormal, int lineCount, float border, std::shared_ptr<GLSLProgram> shader, float textSize, const std::vector<std::string> &texts, std::string texKey, std::vector<std::vector<std::shared_ptr<Texture> > > &textures, std::vector<std::vector<glm::dvec2> > &sizes) { float sx, sy, lh = 0; unsigned int white = glfonsRGBA(255,255,255,255); unsigned int gray = glfonsRGBA(81, 76, 76, 255); fonsClearState(fs); fonsSetSize(fs, textSize); fonsSetFont(fs, fontNormal); fonsSetColor(fs, white); fonsSetAlign(fs, FONS_ALIGN_CENTER | FONS_ALIGN_TOP); fonsVertMetrics(fs, NULL, NULL, &lh); for(int i=0; i < texts.size(); i++) { std::stringstream ss(texts[i]); std::string line; std::vector<std::string> lines; float maxWidth = 0; while(std::getline(ss, line, '\n')){ float width = fonsTextBounds(fs, line.c_str(), NULL, NULL); if (width > maxWidth) { maxWidth = width; } lines.push_back(line); } sx = maxWidth + (1.0f*border); sy = border; if (lineCount > lines.size()) { sy += lh * (lineCount - lines.size()) * 0.5; } float height = lh*lineCount+2.0*border; std::shared_ptr<Texture> depthTexture = Texture::createEmpty("depthTex", sx, height, 1, 1, false, GL_TEXTURE_2D, GL_DEPTH_COMPONENT32F); depthTexture->setTexParameteri(GL_TEXTURE_MIN_FILTER, GL_LINEAR); depthTexture->setTexParameteri(GL_TEXTURE_MAG_FILTER, GL_LINEAR); depthTexture->setTexParameteri(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); depthTexture->setTexParameteri(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture->getID(), 0); textures[threadId][i] = Texture::createEmpty("colorTex", sx, height, 1, 4, false, GL_TEXTURE_2D, GL_RGBA8); textures[threadId][i]->setTexParameteri(GL_TEXTURE_MIN_FILTER, GL_LINEAR); textures[threadId][i]->setTexParameteri(GL_TEXTURE_MAG_FILTER, GL_LINEAR); textures[threadId][i]->setTexParameteri(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); textures[threadId][i]->setTexParameteri(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); textures[threadId][i]->setTexParameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textures[threadId][i]->getID(), 0); GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: assert(false); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: assert(false); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: assert(false); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: assert(false); break; case GL_FRAMEBUFFER_UNSUPPORTED: assert(false); break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: assert(false); break; default: break; } assert(status == GL_FRAMEBUFFER_COMPLETE); sizes[threadId].push_back(glm::dvec2(sx, height)); glViewport(0,0, sx, height); glClear(GL_COLOR_BUFFER_BIT); shader->setUniform("projection_mat", glm::ortho(0., (double)sx, (double)height, 0., -1., 1.)); shader->setUniform("view_mat", glm::dmat4(1.0)); shader->setUniform("model_mat", glm::dmat4(1.0)); shader->setUniform("has_lambertian_texture", false); glDisable(GL_DEPTH_TEST); // Draw the darker interior quad so we get a white border around the outside from the clear color float rim = border/4.0f; GLfloat vertices[] = {rim, height-rim, sx-rim, height-rim, rim, rim, sx-rim, rim}; GLfloat texCoords[] = { 0, 1, 1, 1, 1, 0, 0, 0 }; GLfloat colors[] = { 0.32, 0.3, 0.3, 1.0, 0.32, 0.3, 0.3, 1.0, 0.32, 0.3, 0.3, 1.0, 0.32, 0.3, 0.3, 1.0}; // create the vao GLuint vaoID = 0; glGenVertexArrays(1, &vaoID); glBindVertexArray(vaoID); GLuint quadVBO = 0; glGenBuffers(1, &quadVBO); glBindBuffer(GL_ARRAY_BUFFER, quadVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(texCoords)+sizeof(colors), 0, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // copy vertices starting from 0 offest glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(texCoords), texCoords); // copy texCoords after vertices glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(texCoords), sizeof(colors), colors); // copy colours after normals // set up vertex attributes glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)sizeof(vertices)); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(vertices)+sizeof(texCoords))); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); glDeleteBuffers(1, &quadVBO); glDeleteVertexArrays(1, &vaoID); shader->setUniform("has_lambertian_texture", true); glActiveTexture(GL_TEXTURE0); shader->setUniform("lambertian_texture", 0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for(int j=0; j < lines.size(); j++) { std::string text = boost::replace_all_copy(lines[j], "_", " "); fonsDrawText(fs, sx/2.0, sy, text.c_str(), NULL); sy += lh; } glDisable(GL_BLEND); textures[threadId][i]->generateMipMaps(); std::string textureKey = texKey + texts[i]; texMan->setTextureEntry(threadId, textureKey, textures[threadId][i]); depthTexture.reset(); } }