void Text::updateMetrics(FontResource &fontResource) { _width = 0; _height = 0; for (uint i = 0; i < _text.size(); ++i) { const Common::Rect &curRect = fontResource.getCharacterRect((byte)_text[i]); _width += curRect.width(); if (i != _text.size() - 1) _width += fontResource.getGapWidth(); if (_height < curRect.height()) _height = curRect.height(); } }
void FontLoader::loadPendingFonts() { ASSERT(m_resourceFetcher); FontsToLoadVector fontsToBeginLoading; fontsToBeginLoading.swap(m_fontsToBeginLoading); for (FontsToLoadVector::iterator it = fontsToBeginLoading.begin(); it != fontsToBeginLoading.end(); ++it) { FontResource* fontResource = it->first.get(); fontResource->beginLoadIfNeeded(m_resourceFetcher); } // When the local fontsToBeginLoading vector goes out of scope it will // decrement the request counts on the ResourceFetcher for all the fonts // that were just loaded. }
bool Text::doRender() { // Font-Resource locken. FontResource *fontPtr = lockFontResource(); if (!fontPtr) return false; // Charactermap-Resource locken. ResourceManager *rmPtr = getResourceManager(); BitmapResource *charMapPtr; { Resource *pResource = rmPtr->requestResource(fontPtr->getCharactermapFileName()); if (!pResource) { BS_LOG_ERRORLN("Could not request resource \"%s\".", fontPtr->getCharactermapFileName().c_str()); return false; } if (pResource->getType() != Resource::TYPE_BITMAP) { BS_LOG_ERRORLN("Requested resource \"%s\" is not a bitmap.", fontPtr->getCharactermapFileName().c_str()); return false; } charMapPtr = static_cast<BitmapResource *>(pResource); } // Framebufferobjekt holen. GraphicEngine *gfxPtr = Kernel::getInstance()->getGfx(); BS_ASSERT(gfxPtr); bool result = true; Common::Array<Line>::iterator iter = _lines.begin(); for (; iter != _lines.end(); ++iter) { // Feststellen, ob überhaupt Buchstaben der aktuellen Zeile vom Update betroffen sind. Common::Rect checkRect = (*iter).bbox; checkRect.translate(_absoluteX, _absoluteY); // Jeden Buchstaben einzeln Rendern. int curX = _absoluteX + (*iter).bbox.left; int curY = _absoluteY + (*iter).bbox.top; for (uint i = 0; i < (*iter).text.size(); ++i) { Common::Rect curRect = fontPtr->getCharacterRect((byte)(*iter).text[i]); Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height()); int renderX = curX + (renderRect.left - renderRect.left); int renderY = curY + (renderRect.top - renderRect.top); renderRect.translate(curRect.left - curX, curRect.top - curY); result = charMapPtr->blit(renderX, renderY, Image::FLIP_NONE, &renderRect, _modulationColor); if (!result) break; curX += curRect.width() + fontPtr->getGapWidth(); } } // Charactermap-Resource freigeben. charMapPtr->release(); // Font-Resource freigeben. fontPtr->release(); return result; }
bool Text::doRender(RectangleList *updateRects) { // lock Font Resource FontResource *fontPtr = lockFontResource(); if (!fontPtr) return false; // lock Character map resource ResourceManager *rmPtr = getResourceManager(); BitmapResource *charMapPtr; { Resource *pResource = rmPtr->requestResource(fontPtr->getCharactermapFileName()); if (!pResource) { warning("Could not request resource \"%s\".", fontPtr->getCharactermapFileName().c_str()); return false; } if (pResource->getType() != Resource::TYPE_BITMAP) { error("Requested resource \"%s\" is not a bitmap.", fontPtr->getCharactermapFileName().c_str()); return false; } charMapPtr = static_cast<BitmapResource *>(pResource); } // Getting frame buffer object GraphicEngine *gfxPtr = Kernel::getInstance()->getGfx(); assert(gfxPtr); bool result = true; Common::Array<Line>::iterator iter = _lines.begin(); for (; iter != _lines.end(); ++iter) { // Determine whether any letters of the current line are affected by the update. Common::Rect checkRect = (*iter).bbox; checkRect.translate(_absoluteX, _absoluteY); // Render each letter individually. int curX = _absoluteX + (*iter).bbox.left; int curY = _absoluteY + (*iter).bbox.top; for (uint i = 0; i < (*iter).text.size(); ++i) { Common::Rect curRect = fontPtr->getCharacterRect((byte)(*iter).text[i]); Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height()); renderRect.translate(curRect.left - curX, curRect.top - curY); result = charMapPtr->blit(curX, curY, Graphics::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects); if (!result) break; curX += curRect.width() + fontPtr->getGapWidth(); } } // Free Character map resource charMapPtr->release(); // Free Font resource fontPtr->release(); return result; }
void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip) { xml_node<>* child; if (!resList) return; child = resList->first_node("resource"); while (child != NULL) { xml_attribute<>* attr = child->first_attribute("type"); if (!attr) break; std::string type = attr->value(); if (type == "font") { FontResource* res = new FontResource(child, pZip); if (res == NULL || res->GetResource() == NULL) { xml_attribute<>* attr_name = child->first_attribute("name"); if (!attr_name) { std::string res_name = attr_name->value(); LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str()); } else LOGERR("Resource type (%s) failed to load\n", type.c_str()); delete res; } else { mResources.push_back((Resource*) res); } } else if (type == "image") { ImageResource* res = new ImageResource(child, pZip); if (res == NULL || res->GetResource() == NULL) { xml_attribute<>* attr_name = child->first_attribute("name"); if (!attr_name) { std::string res_name = attr_name->value(); LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str()); } else LOGERR("Resource type (%s) failed to load\n", type.c_str()); delete res; } else { mResources.push_back((Resource*) res); } } else if (type == "animation") { AnimationResource* res = new AnimationResource(child, pZip); if (res == NULL || res->GetResource() == NULL) { xml_attribute<>* attr_name = child->first_attribute("name"); if (!attr_name) { std::string res_name = attr_name->value(); LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str()); } else LOGERR("Resource type (%s) failed to load\n", type.c_str()); delete res; } else { mResources.push_back((Resource*) res); } } else { LOGERR("Resource type (%s) not supported.\n", type.c_str()); } child = child->next_sibling("resource"); } }
void C_Renderer::CalculateRect(IResource* font, RectangleI* pt, const wchar_t* str, unsigned int start, unsigned int end, unsigned int style, float scale) { if(font==0) return; #ifdef USE_BITMAPFONT Sprite* Font = CAST_RES(Sprite*, font); FontResource* rc = (FontResource*)font; #else LPD3DXFONT Font = CAST_RES(LPD3DXFONT, font); #endif if(Font==0) return; #ifdef USE_BITMAPFONT #else D3DXMatrixScaling(&mat, scale, scale, 1.0f); m_sprite->GetTransform(&m2); m_sprite->SetTransform(&(mat * m2)); pt->left = (LONG)(pt->left/scale); pt->top = (LONG)(pt->top/scale); pt->right = (LONG)(pt->right/scale); pt->bottom = (LONG)(pt->bottom/scale); #endif #ifdef USE_BITMAPFONT float sw = 0.0f; RectangleI* rct = 0; RectangleF rect; rect.left = (float)pt->left; rect.top = (float)pt->top; rect.right = (float)pt->right; rect.bottom = (float)pt->bottom; unsigned int txtsize = wcslen(str); float fsize = (float)rc->GetSize(); if(start>=txtsize || end>txtsize) return; float fwidth = 0.0f; float fheight = 0.0f; for(unsigned int i=start; i< start + end; i++) { rct = Font->GetSpriteRect((unsigned int)str[i]); if(rct!=0) { float scale2 = fsize / (rct->bottom - rct->top); fwidth += ((rct->right - rct->left - BFONTSPACEW) * scale2) * scale; fheight = ((rct->bottom - rct->top) * scale2) * scale; } } if(style&FONT_STYLE_MULTILINE) { rect.left -= BFONTSPACE; rect.right -= BFONTSPACE; } else { rect.left -= BFONTSPACE; rect.right = rect.left + fwidth - BFONTSPACE; rect.bottom = rect.top + fheight; pt->left = (int)(rect.left/scale); pt->top = (int)(rect.top/scale); pt->right = (int)(rect.right/scale); pt->bottom = (int)(rect.bottom/scale); } #else Font->DrawTextW(m_sprite, str + start, end, (LPRECT)pt, style | DT_CALCRECT, D3DXCOLOR(0,0,0,1)); m_sprite->SetTransform(&m2); #endif }
void C_Renderer::DrawText(IResource* font, const wchar_t* text, int dx, int dy, int dr, int db, unsigned int color, unsigned int style, float scale, int Drawonly) { if(font==0) return; #ifdef USE_BITMAPFONT Sprite* Font = CAST_RES(Sprite*, font); FontResource* rc = (FontResource*)font; #else LPD3DXFONT Font = CAST_RES(LPD3DXFONT, font); #endif if(Font==0) return; #ifdef USE_BITMAPFONT #else D3DXMatrixScaling(&mat, scale, scale, 1.0f); m_sprite->GetTransform(&m2); m_sprite->SetTransform(&(mat * m2)); rect.left = (LONG)(dx/scale); rect.top = (LONG)(dy/scale); rect.right = (LONG)(dr/scale); rect.bottom = (LONG)(db/scale); #endif #ifdef USE_BITMAPFONT float sw = 0.0f; RectangleI* rct = 0; RectangleF rect; rect.left = (float)dx; rect.top = (float)dy; rect.right = (float)dr; rect.bottom = (float)db; unsigned int txtsize = wcslen(text); float fsize = (float)rc->GetSize(); float fwidth = 0.0f; float fheight = 0.0f; for(unsigned int i=0; i<txtsize; i++) { rct = Font->GetSpriteRect((unsigned int)text[i]); if(rct!=0) { float scale2 = fsize / (rct->bottom - rct->top); fwidth += ((rct->right - rct->left - BFONTSPACEW) * scale2) * scale; fheight = ((rct->bottom - rct->top) * scale2) * scale; } } if(style&FONT_STYLE_MULTILINE) { rect.left -= BFONTSPACE; rect.right -= BFONTSPACE; } else { if(style&FONT_STYLE_CENTERALIGN) { float hfwidth = fwidth / 2.0f; float hwidth = (rect.right - rect.left) / 2.0f; rect.left = (rect.left + hwidth) - hfwidth - BFONTSPACEW; rect.right = rect.left + fwidth - BFONTSPACEW; } else if(style&FONT_STYLE_RIGHTALIGN) { rect.left = rect.right - fwidth - BFONTSPACE; rect.right = rect.left + fwidth - BFONTSPACE; } else { rect.left -= BFONTSPACE; rect.right = rect.left + fwidth - BFONTSPACE; } if(style&FONT_STYLE_VCENTERALIGN) { float hfheight = fheight / 2.0f; float hheight = (rect.bottom - rect.top) / 2.0f; rect.top = (rect.top + hheight) - hfheight; rect.bottom = rect.top + fheight; } else if(style&FONT_STYLE_BOTTOMALIGN) { rect.top = rect.bottom - fheight; rect.right = rect.top + fheight; } else { rect.bottom = rect.top + fheight; } } float ty = 0.0f; float tx = 0; for(unsigned int i=0; i<txtsize; i++) { rct = Font->GetSpriteRect((unsigned int)text[i]); if(rct!=0) { float scale2 = fsize / (rct->bottom - rct->top); if(style&FONT_STYLE_MULTILINE) { RectangleF rect2 = rect; rect2.left = rect.left + tx; rect2.right = (rect2.left + (rct->right - rct->left) * scale2 * scale); if(rect2.right>rect.right || text[i] == L'\n' || text[i] == L'\r') { ty += fsize * scale + BFONTVSPACE; tx = 0; rect2.left = rect.left + tx; rect2.right = (rect2.left + (rct->right - rct->left) * scale2 * scale); } rect2.top = rect.top + ty; rect2.bottom = (rect2.top + fsize * scale); if(!(text[i] == L'\n' || text[i] == L'\r')) { Font->SetIndex((unsigned int)text[i]); if(Drawonly==-1 || Drawonly==i) Font->Draw(this, rect2, color, 0.0f, 0.0f); tx += ((rct->right - rct->left - BFONTSPACEW) * scale2) * scale; } } else { rect.right = (rect.left + (rct->right - rct->left) * scale2 * scale); rect.bottom = (rect.top + fsize * scale); Font->SetIndex((unsigned int)text[i]); if(Drawonly==-1 || Drawonly==i) Font->Draw(this, rect, color, 0.0f, 0.0f); rect.left += ((rct->right - rct->left - BFONTSPACEW) * scale2) * scale; } } } #else Font->DrawTextW(m_sprite, text, -1, (LPRECT)&rect, style, color); m_sprite->SetTransform(&m2); #endif }
void Text::updateFormat() { FontResource *fontPtr = lockFontResource(); assert(fontPtr); updateMetrics(*fontPtr); _lines.resize(1); if (_autoWrap && (uint) _width >= _autoWrapThreshold && _text.size() >= 2) { _width = 0; uint curLineWidth = 0; uint curLineHeight = 0; uint curLine = 0; uint tempLineWidth = 0; uint lastSpace = 0; // we need at least 1 space character to start a new line... _lines[0].text = ""; for (uint i = 0; i < _text.size(); ++i) { uint j; tempLineWidth = 0; lastSpace = 0; for (j = i; j < _text.size(); ++j) { if ((byte)_text[j] == ' ') lastSpace = j; const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]); tempLineWidth += curCharRect.width(); tempLineWidth += fontPtr->getGapWidth(); if ((tempLineWidth >= _autoWrapThreshold) && (lastSpace > 0)) break; } if (j == _text.size()) // everything in 1 line. lastSpace = _text.size(); curLineWidth = 0; curLineHeight = 0; for (j = i; j < lastSpace; ++j) { _lines[curLine].text += _text[j]; const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]); curLineWidth += curCharRect.width(); curLineWidth += fontPtr->getGapWidth(); if ((uint)curCharRect.height() > curLineHeight) curLineHeight = curCharRect.height(); } _lines[curLine].bbox.right = curLineWidth; _lines[curLine].bbox.bottom = curLineHeight; if ((uint)_width < curLineWidth) _width = curLineWidth; if (lastSpace < _text.size()) { ++curLine; assert(curLine == _lines.size()); _lines.resize(curLine + 1); _lines[curLine].text = ""; } i = lastSpace; } // Bounding box of each line relative to the first set (center aligned). _height = 0; Common::Array<Line>::iterator iter = _lines.begin(); for (; iter != _lines.end(); ++iter) { Common::Rect &bbox = (*iter).bbox; bbox.left = (_width - bbox.right) / 2; bbox.right = bbox.left + bbox.right; bbox.top = (iter - _lines.begin()) * fontPtr->getLineHeight(); bbox.bottom = bbox.top + bbox.bottom; _height += bbox.height(); } } else { // No auto format, so all the text is copied to a single line. _lines[0].text = _text; _lines[0].bbox = Common::Rect(0, 0, _width, _height); } fontPtr->release(); }
void Environment::renderScreen() { SDL_Rect q,r; Element *t; char buf[255]; char *bufp; // if we're in a fadeout, use a faded mBuffer and just blit it to // the screen if (mMenuState == State_ChangeMenu && mMenuStatePosition == 1) { SDL_BlitSurface(mScreen, 0x00, mBuffer, 0x00); /*SDL_SetAlpha(mBuffer, SDL_SRCALPHA, 255-(mMenuStatePosition*10)); SDL_FillRect(mScreen, 0, 0); SDL_BlitSurface(mBuffer, 0x00, mScreen, 0x00); SDL_Flip(mScreen); return; */ } // draw background t = mElements->getElementByContent(CONTENT_BACKGROUND_IMAGE, mMenu->getSkinID()); if (t) { t->drawImage(mScreen); } //if (t && t->getResource() /*&& typeid(*t->getResource()) == typeid(ImageResource) */) { // ImageResource *tmp = (ImageResource *) t->getResource(); // SDL_BlitSurface(tmp->getImage(), 0x00, mScreen, 0); //} // draw menu in proper dimensions t = mElements->getElementByContent(CONTENT_MENU, mMenu->getSkinID()); if (mMenuSurface && t) { r = t->getDimensions(); q.w = r.w; q.h = r.h; q.x = 0; q.y = (mMenuOffset-50-mMenuRenderOffset); if (q.y < 0) { q.y = 0; } SDL_BlitSurface(mMenuSurface, &q, mScreen, &r); } // draw the remaining Elements. List<Element> *e = mElements->getElements(); while (e) { if (e->getData() && (!e->getData()->getSkinID() || !e->getData()->getSkinID() || !strcmp(e->getData()->getSkinID(), mMenu->getSkinID()))) { if (e->getData()->getContent() == CONTENT_STATUS) { if (mSelectedNode && mSelectedNode->getStatusText()) { e->getData()->drawText(mSelectedNode->getStatusText(), mScreen); } } else if (e->getData()->getContent() == CONTENT_BOARDTEMP) { sprintf(buf, "%d C", mXboxInfo->getBoardTemp()); e->getData()->drawText(buf, mScreen); } else if (e->getData()->getContent() == CONTENT_CPUTEMP) { sprintf(buf, "%d C", mXboxInfo->getCPUTemp()); e->getData()->drawText(buf, mScreen); } else if (e->getData()->getContent() == CONTENT_TRAYSTATE) { FontResource *fRes = (FontResource *) e->getData()->getResource(); int i = mXboxInfo->getTrayState(); if (i == Tray_Open) { if (mDialog && (bufp = mDialog->getValue("TrayOpen"))) { strcpy(buf, bufp); } else { sprintf(buf, "Open"); } } else if (i == Tray_NoDisk) { if (mDialog && (bufp = mDialog->getValue("TrayNoDisk"))) { strcpy(buf, bufp); } else { sprintf(buf, "No Disk"); } } else if (i == Tray_Disk) { if (mDialog && (bufp == mDialog->getValue("TrayDisk"))) { strcpy(buf, bufp); } else { sprintf(buf, "Disk"); } } else if (i == Tray_Opening) { if (mDialog && (bufp == mDialog->getValue("TrayOpening"))) { strcpy(buf, bufp); } else { sprintf(buf, "Opening"); } } else if (i == Tray_Closing) { if (mDialog && (bufp == mDialog->getValue("TrayClosing"))) { strcpy(buf, bufp); } else { sprintf(buf, "Closing"); } } else if (i == Tray_Reading) { if (mDialog && (bufp == mDialog->getValue("TrayBusy"))) { strcpy(buf, bufp); } else { sprintf(buf, "Busy"); } } if (fRes && fRes->getFont()) { e->getData()->drawText(buf, mScreen); } } } e = e->getLink(); } }
void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH) { unsigned char keychar = key.key; if (!keychar) return; // key background COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther; gr_color(c.red, c.green, c.blue, c.alpha); keyX += mKeyMarginX; keyY += mKeyMarginY; keyW -= mKeyMarginX * 2; keyH -= mKeyMarginY * 2; gr_fill(keyX, keyY, keyW, keyH); // key label FontResource* labelFont = mFont; string labelText; ImageResource* labelImage = NULL; if (keychar > 32 && keychar < 127) { labelText = (char) keychar; gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha); } else { // search for a special key label for (std::vector<KeyLabel>::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) { if (it->layout_from > 0 && it->layout_from != currentLayout) continue; // this label is for another layout if (it->key == key.key && it->layout_to == key.layout) { // found a label labelText = it->text; labelImage = it->image; break; } } labelFont = mSmallFont; gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha); } if (labelImage) { int w = labelImage->GetWidth(); int h = labelImage->GetHeight(); int x = keyX + (keyW - w) / 2; int y = keyY + (keyH - h) / 2; gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y); } else if (!labelText.empty()) { void* fontResource = labelFont->GetResource(); int textW = gr_measureEx(labelText.c_str(), fontResource); int textH = labelFont->GetHeight(); int textX = keyX + (keyW - textW) / 2; int textY = keyY + (keyH - textH) / 2; gr_textEx(textX, textY, labelText.c_str(), fontResource); } // longpress key label (only if font is defined) keychar = key.longpresskey; if (keychar > 32 && keychar < 127 && mLongpressFont->GetResource()) { void* fontResource = mLongpressFont->GetResource(); gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha); string text(1, keychar); int textH = mLongpressFont->GetHeight(); int textW = gr_measureEx(text.c_str(), fontResource); int textX = keyX + keyW - longpressOffsetX - textW; int textY = keyY + longpressOffsetY; gr_textEx(textX, textY, text.c_str(), fontResource); } }
void Text::updateFormat() { FontResource *fontPtr = lockFontResource(); BS_ASSERT(fontPtr); updateMetrics(*fontPtr); _lines.resize(1); if (_autoWrap && (uint) _width >= _autoWrapThreshold && _text.size() >= 2) { _width = 0; uint curLineWidth = 0; uint curLineHeight = 0; uint curLine = 0; uint tempLineWidth = 0; uint lastSpace = 0; // we need at least 1 space character to start a new line... _lines[0].text = ""; for (uint i = 0; i < _text.size(); ++i) { uint j; tempLineWidth = 0; lastSpace = 0; for (j = i; j < _text.size(); ++j) { if ((byte)_text[j] == ' ') lastSpace = j; const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]); tempLineWidth += curCharRect.width(); tempLineWidth += fontPtr->getGapWidth(); if ((tempLineWidth >= _autoWrapThreshold) && (lastSpace > 0)) break; } if (j == _text.size()) // everything in 1 line. lastSpace = _text.size(); curLineWidth = 0; curLineHeight = 0; for (j = i; j < lastSpace; ++j) { _lines[curLine].text += _text[j]; const Common::Rect &curCharRect = fontPtr->getCharacterRect((byte)_text[j]); curLineWidth += curCharRect.width(); curLineWidth += fontPtr->getGapWidth(); if ((uint)curCharRect.height() > curLineHeight) curLineHeight = curCharRect.height(); } _lines[curLine].bbox.right = curLineWidth; _lines[curLine].bbox.bottom = curLineHeight; if ((uint)_width < curLineWidth) _width = curLineWidth; if (lastSpace < _text.size()) { ++curLine; BS_ASSERT(curLine == _lines.size()); _lines.resize(curLine + 1); _lines[curLine].text = ""; } i = lastSpace; } // Bounding-Box der einzelnen Zeilen relativ zur ersten festlegen (vor allem zentrieren). _height = 0; Common::Array<Line>::iterator iter = _lines.begin(); for (; iter != _lines.end(); ++iter) { Common::Rect &bbox = (*iter).bbox; bbox.left = (_width - bbox.right) / 2; bbox.right = bbox.left + bbox.right; bbox.top = (iter - _lines.begin()) * fontPtr->getLineHeight(); bbox.bottom = bbox.top + bbox.bottom; _height += bbox.height(); } } else { // Keine automatische Formatierung, also wird der gesamte Text in nur eine Zeile kopiert. _lines[0].text = _text; _lines[0].bbox = Common::Rect(0, 0, _width, _height); } fontPtr->release(); }
void Ui::print(const std::string &fontfile, int x, int y, const std::string &in) { static uint32_t vertex_buffer = 0; static uint32_t uv_buffer = 0; static Shader shader; static bool first = true; if (first) { shader.attach("shaders/font.frag"); shader.attach("shaders/font.vert"); first = false; } glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (shader.use()) { FontResource *font = engine.resources.getFont(fontfile.c_str()); if (font) { if (!vertex_buffer) { glGenBuffers(1, &vertex_buffer); } if (!uv_buffer) { glGenBuffers(1, &uv_buffer); } TextData *text = font->print(in); shader.setUniform("in_UiPos", glm::vec2(x, y)); shader.setUniform("in_Color", glm::vec4(1, 1, 1, 1)); shader.setUniform("in_OrthoMatrix", engine.video.OrthoMat); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, font->id); shader.setUniform("FontTexture", 0); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBufferData( GL_ARRAY_BUFFER, sizeof(glm::vec2) * text->verts.size(), &text->verts[0], GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, uv_buffer); glBufferData( GL_ARRAY_BUFFER, sizeof(glm::vec2) * text->uvs.size(), &text->uvs[0], GL_STATIC_DRAW); shader.bindAttribLocation(0, "in_Position"); shader.bindAttribLocation(1, "in_TexCoord"); glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), nullptr); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, uv_buffer); glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), nullptr); glEnableVertexAttribArray(1); glDrawArrays(GL_QUADS, 0, text->verts.size()); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glUseProgram(0); delete text; } } glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); }