From 1c965736e80477a9f4a69d56f6055b5a8dd838ce Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 17 Jul 2015 18:15:11 -0700 Subject: [PATCH] Remove merge error --- libraries/render-utils/src/TextRenderer3D.cpp | 403 ------------------ 1 file changed, 403 deletions(-) diff --git a/libraries/render-utils/src/TextRenderer3D.cpp b/libraries/render-utils/src/TextRenderer3D.cpp index b88883ba64..a93ba1daec 100644 --- a/libraries/render-utils/src/TextRenderer3D.cpp +++ b/libraries/render-utils/src/TextRenderer3D.cpp @@ -33,409 +33,6 @@ #include "GeometryCache.h" #include "DeferredLightingEffect.h" -<<<<<<< HEAD -// Helper functions for reading binary data from an IO device -template -void readStream(QIODevice& in, T& t) { - in.read((char*) &t, sizeof(t)); -} - -template -void readStream(QIODevice& in, T (&t)[N]) { - in.read((char*) t, N); -} - -template -void fillBuffer(QBuffer& buffer, T (&t)[N]) { - buffer.setData((const char*) t, N); -} - -// stores the font metrics for a single character -struct Glyph3D { - QChar c; - glm::vec2 texOffset; - glm::vec2 texSize; - glm::vec2 size; - glm::vec2 offset; - float d; // xadvance - adjusts character positioning - size_t indexOffset; - - // We adjust bounds because offset is the bottom left corner of the font but the top left corner of a QRect - QRectF bounds() const { return glmToRect(offset, size).translated(0.0f, -size.y); } - QRectF textureBounds() const { return glmToRect(texOffset, texSize); } - - void read(QIODevice& in); -}; - -void Glyph3D::read(QIODevice& in) { - uint16_t charcode; - readStream(in, charcode); - c = charcode; - readStream(in, texOffset); - readStream(in, size); - readStream(in, offset); - readStream(in, d); - texSize = size; -} - -struct TextureVertex { - glm::vec2 pos; - glm::vec2 tex; - TextureVertex() {} - TextureVertex(const glm::vec2& pos, const glm::vec2& tex) : pos(pos), tex(tex) {} -}; - -struct QuadBuilder { - TextureVertex vertices[4]; - QuadBuilder(const glm::vec2& min, const glm::vec2& size, - const glm::vec2& texMin, const glm::vec2& texSize) { - // min = bottomLeft - vertices[0] = TextureVertex(min, - texMin + glm::vec2(0.0f, texSize.y)); - vertices[1] = TextureVertex(min + glm::vec2(size.x, 0.0f), - texMin + texSize); - vertices[2] = TextureVertex(min + size, - texMin + glm::vec2(texSize.x, 0.0f)); - vertices[3] = TextureVertex(min + glm::vec2(0.0f, size.y), - texMin); - } - QuadBuilder(const Glyph3D& glyph, const glm::vec2& offset) : - QuadBuilder(offset + glm::vec2(glyph.offset.x, glyph.offset.y - glyph.size.y), glyph.size, - glyph.texOffset, glyph.texSize) {} - -}; - -class Font3D { -public: - Font3D(); - - void read(QIODevice& path); - - glm::vec2 computeExtent(const QString& str) const; - float getFontSize() const { return _fontSize; } - - // Render string to batch - void drawString(gpu::Batch& batch, float x, float y, const QString& str, - const glm::vec4* color, TextRenderer3D::EffectType effectType, - const glm::vec2& bound); - -private: - QStringList tokenizeForWrapping(const QString& str) const; - QStringList splitLines(const QString& str) const; - glm::vec2 computeTokenExtent(const QString& str) const; - - const Glyph3D& getGlyph(const QChar& c) const; - - void setupGPU(); - - // maps characters to cached glyph info - // HACK... the operator[] const for QHash returns a - // copy of the value, not a const value reference, so - // we declare the hash as mutable in order to avoid such - // copies - mutable QHash _glyphs; - - // Font characteristics - QString _family; - float _fontSize = 0.0f; - float _leading = 0.0f; - float _ascent = 0.0f; - float _descent = 0.0f; - float _spaceWidth = 0.0f; - - bool _initialized = false; - - // gpu structures - gpu::PipelinePointer _pipeline; - gpu::TexturePointer _texture; - gpu::Stream::FormatPointer _format; - gpu::BufferPointer _verticesBuffer; - gpu::BufferStreamPointer _stream; - unsigned int _numVertices = 0; - - int _fontLoc = -1; - int _outlineLoc = -1; - int _colorLoc = -1; - - // last string render characteristics - QString _lastStringRendered; - glm::vec2 _lastBounds; -}; - -static QHash LOADED_FONTS; - -Font3D* loadFont3D(QIODevice& fontFile) { - Font3D* result = new Font3D(); - result->read(fontFile); - return result; -} - -Font3D* loadFont3D(const QString& family) { - if (!LOADED_FONTS.contains(family)) { - - const QString SDFF_COURIER_PRIME_FILENAME = ":/CourierPrime.sdff"; - const QString SDFF_INCONSOLATA_MEDIUM_FILENAME = ":/InconsolataMedium.sdff"; - const QString SDFF_ROBOTO_FILENAME = ":/Roboto.sdff"; - const QString SDFF_TIMELESS_FILENAME = ":/Timeless.sdff"; - - QString loadFilename; - - if (family == MONO_FONT_FAMILY) { - loadFilename = SDFF_COURIER_PRIME_FILENAME; - } else if (family == INCONSOLATA_FONT_FAMILY) { - loadFilename = SDFF_INCONSOLATA_MEDIUM_FILENAME; - } else if (family == SANS_FONT_FAMILY) { - loadFilename = SDFF_ROBOTO_FILENAME; - } else { - if (!LOADED_FONTS.contains(SERIF_FONT_FAMILY)) { - loadFilename = SDFF_TIMELESS_FILENAME; - } else { - LOADED_FONTS[family] = LOADED_FONTS[SERIF_FONT_FAMILY]; - } - } - - if (!loadFilename.isEmpty()) { - QFile fontFile(loadFilename); - fontFile.open(QIODevice::ReadOnly); - - qCDebug(renderutils) << "Loaded font" << loadFilename << "from Qt Resource System."; - - LOADED_FONTS[family] = loadFont3D(fontFile); - } - } - return LOADED_FONTS[family]; -} - -Font3D::Font3D() { - static bool fontResourceInitComplete = false; - if (!fontResourceInitComplete) { - Q_INIT_RESOURCE(fonts); - fontResourceInitComplete = true; - } -} - -// NERD RAGE: why doesn't QHash have a 'const T & operator[] const' member -const Glyph3D& Font3D::getGlyph(const QChar& c) const { - if (!_glyphs.contains(c)) { - return _glyphs[QChar('?')]; - } - return _glyphs[c]; -} - -QStringList Font3D::splitLines(const QString& str) const { - return str.split('\n'); -} - -QStringList Font3D::tokenizeForWrapping(const QString& str) const { - QStringList tokens; - for(auto line : splitLines(str)) { - if (!tokens.empty()) { - tokens << QString('\n'); - } - tokens << line.split(' '); - } - return tokens; -} - -glm::vec2 Font3D::computeTokenExtent(const QString& token) const { - glm::vec2 advance(0, _fontSize); - foreach(QChar c, token) { - Q_ASSERT(c != '\n'); - advance.x += (c == ' ') ? _spaceWidth : getGlyph(c).d; - } - return advance; -} - -glm::vec2 Font3D::computeExtent(const QString& str) const { - glm::vec2 extent = glm::vec2(0.0f, 0.0f); - - QStringList lines{ splitLines(str) }; - if (!lines.empty()) { - for(const auto& line : lines) { - glm::vec2 tokenExtent = computeTokenExtent(line); - extent.x = std::max(tokenExtent.x, extent.x); - } - extent.y = lines.count() * _fontSize; - } - return extent; -} - -void Font3D::read(QIODevice& in) { - uint8_t header[4]; - readStream(in, header); - if (memcmp(header, "SDFF", 4)) { - qFatal("Bad SDFF file"); - } - - uint16_t version; - readStream(in, version); - - // read font name - _family = ""; - if (version > 0x0001) { - char c; - readStream(in, c); - while (c) { - _family += c; - readStream(in, c); - } - } - - // read font data - readStream(in, _leading); - readStream(in, _ascent); - readStream(in, _descent); - readStream(in, _spaceWidth); - _fontSize = _ascent + _descent; - - // Read character count - uint16_t count; - readStream(in, count); - // read metrics data for each character - QVector glyphs(count); - // std::for_each instead of Qt foreach because we need non-const references - std::for_each(glyphs.begin(), glyphs.end(), [&](Glyph3D& g) { - g.read(in); - }); - - // read image data - QImage image; - if (!image.loadFromData(in.readAll(), "PNG")) { - qFatal("Failed to read SDFF image"); - } - - _glyphs.clear(); - glm::vec2 imageSize = toGlm(image.size()); - foreach(Glyph3D g, glyphs) { - // Adjust the pixel texture coordinates into UV coordinates, - g.texSize /= imageSize; - g.texOffset /= imageSize; - // store in the character to glyph hash - _glyphs[g.c] = g; - }; - - image = image.convertToFormat(QImage::Format_RGBA8888); - - gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); - gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB); - if (image.hasAlphaChannel()) { - formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA); - formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, gpu::BGRA); - } - _texture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, image.width(), image.height(), - gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); - _texture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); - _texture->autoGenerateMips(-1); -} - -void Font3D::setupGPU() { - if (!_initialized) { - _initialized = true; - - // Setup render pipeline - auto vertexShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(sdf_text3D_vert))); - auto pixelShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(sdf_text3D_frag))); - gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); - - gpu::Shader::BindingSet slotBindings; - gpu::Shader::makeProgram(*program, slotBindings); - - _fontLoc = program->getTextures().findLocation("Font"); - _outlineLoc = program->getUniforms().findLocation("Outline"); - _colorLoc = program->getUniforms().findLocation("Color"); - - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - _pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); - - // Sanity checks - static const int OFFSET = offsetof(TextureVertex, tex); - assert(OFFSET == sizeof(glm::vec2)); - assert(sizeof(glm::vec2) == 2 * sizeof(float)); - assert(sizeof(TextureVertex) == 2 * sizeof(glm::vec2)); - assert(sizeof(QuadBuilder) == 4 * sizeof(TextureVertex)); - - // Setup rendering structures - _format = std::make_shared(); - _format->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); - _format->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), OFFSET); - } -} - -void Font3D::drawString(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4* color, - TextRenderer3D::EffectType effectType, const glm::vec2& bounds) { - if (str == "") { - return; - } - - if (str != _lastStringRendered || bounds != _lastBounds) { - _verticesBuffer = std::make_shared(); - _numVertices = 0; - _lastStringRendered = str; - _lastBounds = bounds; - - // Top left of text - glm::vec2 advance = glm::vec2(x, y); - foreach(const QString& token, tokenizeForWrapping(str)) { - bool isNewLine = (token == QString('\n')); - bool forceNewLine = false; - - // Handle wrapping - if (!isNewLine && (bounds.x != -1) && (advance.x + computeExtent(token).x > x + bounds.x)) { - // We are out of the x bound, force new line - forceNewLine = true; - } - if (isNewLine || forceNewLine) { - // Character return, move the advance to a new line - advance = glm::vec2(x, advance.y - _leading); - - if (isNewLine) { - // No need to draw anything, go directly to next token - continue; - } else if (computeExtent(token).x > bounds.x) { - // token will never fit, stop drawing - break; - } - } - if ((bounds.y != -1) && (advance.y - _fontSize < -y - bounds.y)) { - // We are out of the y bound, stop drawing - break; - } - - // Draw the token - if (!isNewLine) { - for (auto c : token) { - auto glyph = _glyphs[c]; - - QuadBuilder qd(glyph, advance - glm::vec2(0.0f, _ascent)); - _verticesBuffer->append(sizeof(QuadBuilder), (const gpu::Byte*)&qd); - _numVertices += 4; - - // Advance by glyph size - advance.x += glyph.d; - } - - // Add space after all non return tokens - advance.x += _spaceWidth; - } - } - } - - setupGPU(); - batch.setPipeline(_pipeline); - batch.setUniformTexture(_fontLoc, _texture); - batch._glUniform1i(_outlineLoc, (effectType == TextRenderer3D::OUTLINE_EFFECT)); - batch._glUniform4fv(_colorLoc, 1, (const GLfloat*)color); - - batch.setInputFormat(_format); - batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride); - batch.draw(gpu::QUADS, _numVertices, 0); -} -======= const float TextRenderer3D::DEFAULT_POINT_SIZE = 12; TextRenderer3D* TextRenderer3D::getInstance(const char* family, float pointSize,