void PerlinTexture::createTexture() { for (int x = 0; x < m_width; ++x) { for (int y = 0; y < m_height; ++y) { m_texture(y, x) = m_sampler->next1D(); } } }
SWSprite::SWSprite( SWHardRef<SWTexture> texture, int x, int y, int width, int height ) : m_texture( texture ) , m_offset( (float)x, (float)y ) , m_size( (float)width, (float)height ) , m_scaledOffset( 0.0f, 0.0f ) , m_scaledSize( 0.0f, 0.0f ) { if ( m_texture.isValid() ) { float texW = (float)m_texture()->getWidth(); float texH = (float)m_texture()->getHeight(); m_scaledOffset.x = x/texW; m_scaledOffset.y = y/texH; m_scaledSize.x = width/texW; m_scaledSize.y = height/texH; } }
void SWSprite::serialize( SWObjectWriter* writer ) { tstring path; bool isAsset = SWAssets.findPathOfTexture( m_texture(), path ); writer->writeBool( isAsset ); if ( isAsset ) writer->writeString( path ); writer->writeVec2( m_offset ); writer->writeVec2( m_size ); writer->writeVec2( m_scaledOffset ); writer->writeVec2( m_scaledSize ); }
void PerlinTexture::bilinearInterpolated(float x, float y, float &result) const { int x1 = int(x); int y1 = int(y); int x2 = (x1 + 1); int y2 = (y1 + 1); float Q11 = 0.0f; float Q21 = 0.0f; float Q12 = 0.0f; float Q22 = 0.0f; if(x1 < m_width && y1 < m_height) { Q11 = m_texture(y1, x1); } if(x2 < m_width && y1 < m_height) { Q21 = m_texture(y1, x2);; } if(x1 < m_width && y2 < m_height) { Q12 = m_texture(y2, x1); } if(x2 < m_width && y1 < m_height) { Q22 = m_texture(y2, x2);; } float fact1 = ((x2 - x) / (x2 - x1)); float fact2 = ((x - x1) / (x2 - x1)); float R1 = fact1 * Q11 + fact2 * Q21; float R2 = fact1 * Q12 + fact2 * Q22; fact1 = ((y2 - y) / (y2 - y1)); fact2 = ((y - y1) / (y2 - y1)); result = fact1 * R1 + fact2 * R2; }
RectF FontData::draw(const String& codePoints, const Vec2& pos, const ColorF& color, double lineSpacingScale) { if (!render(codePoints)) { return RectF(pos, 0); } Vec2 penPos(pos); double maxPosX = DBL_MIN; int32 lineCount = 0; for (const auto codePoint : codePoints) { if (codePoint == U'\n') { penPos.x = pos.x; penPos.y += m_lineSpacing * lineSpacingScale; ++lineCount; continue; } else if (codePoint == U'\t') { maxPosX = std::max(maxPosX, penPos.x + m_tabWidth); penPos.x += m_tabWidth; continue; } else if (!IsControl(codePoint)) { if (lineCount == 0) { ++lineCount; } const auto& glyphInfo = m_glyphs[m_glyphIndexTable[codePoint]]; const RectF region = m_texture(glyphInfo.bitmapRect).draw(penPos + glyphInfo.offset, color); const int32 characterWidth = glyphInfo.xAdvance; maxPosX = std::max(maxPosX, region.x + characterWidth); penPos.x += glyphInfo.xAdvance; } } if (!lineCount) { return RectF(pos, 0); } return RectF(pos, maxPosX - pos.x, lineCount * m_lineSpacing * lineSpacingScale); }
Array<Glyph> FontData::getGlyphs(const String& codePoints) { if (!render(codePoints)) { return Array<Glyph>(codePoints.size()); } Array<Glyph> glyphs; int32 index = 0; for (const auto codePoint : codePoints) { Glyph glyph; glyph.codePoint = codePoint; glyph.index = index; if (codePoint == U'\n') { } else if (codePoint == U'\t') { glyph.xAdvance = m_tabWidth; } else if (IsControl(codePoint)) { } else { const auto& glyphInfo = m_glyphs[m_glyphIndexTable[codePoint]]; glyph.texture = m_texture(glyphInfo.bitmapRect); glyph.offset = glyphInfo.offset; glyph.bearingY = glyphInfo.bearingY; glyph.xAdvance = glyphInfo.xAdvance; } glyphs.push_back(glyph); ++index; } return glyphs; }
void SWFontRenderer::render( SWCamera* camera ) { if ( !getMesh() ) return; if ( !getMaterial() ) return; if ( !m_texture.isValid() ) return; if ( m_text.size() == 0 ) return; if ( m_textChanged ) { m_textChanged = false; updateMesh(); } SWTransform* transform = gameObject()->getComponent<SWTransform>(); const TMatrix4x4& model = transform->getWorldMatrix(); const TMatrix4x4& VPMat = camera->getVPMatrix(); SWMaterial* material = getMaterial(); material->setTexture( "TEXTURE_0", m_texture() ); material->setMatrix4x4( "MATRIX_MVP", ( model * VPMat ) ); material->apply(); getMesh()->draw(); }
bool FontData::draw(const String& codePoints, const RectF& area, const ColorF& color, const double lineSpacingScale) { if (!render(codePoints)) { return false; } const double width = area.w; const double height = area.h; std::u32string adjustedText; bool needDots = false; if (m_lineSpacing > height) { return false; } { Vec2 penPos(0, 0); for (const auto& codePoint : codePoints) { if (codePoint == U'\n') { penPos.y += m_lineSpacing * lineSpacingScale; if (penPos.y + m_lineSpacing <= height) { penPos.x = 0; adjustedText.push_back(U'\n'); continue; } else { needDots = true; break; } } else if (codePoint == U'\t') { const int32 characterWidth = m_tabWidth; if (penPos.x + characterWidth <= width) { penPos.x += characterWidth; adjustedText.push_back(codePoint); continue; } else { penPos.y += m_lineSpacing * lineSpacingScale; if (penPos.y + m_lineSpacing <= height) { if (characterWidth > width) { return false; } penPos.x = characterWidth; adjustedText.push_back(U'\n'); adjustedText.push_back(codePoint); continue; } else { needDots = true; break; } } } else if (IsControl(codePoint)) { continue; } const auto& glyphInfo = m_glyphs[m_glyphIndexTable[codePoint]]; const int32 characterWidth = glyphInfo.offset.x + glyphInfo.bitmapRect.w; if (penPos.x + characterWidth <= width) { penPos.x += glyphInfo.xAdvance; adjustedText.push_back(codePoint); continue; } else { penPos.y += m_lineSpacing * lineSpacingScale; if (penPos.y + m_lineSpacing <= height) { if (glyphInfo.xAdvance > width) { return false; } penPos.x = glyphInfo.xAdvance; adjustedText.push_back(U'\n'); adjustedText.push_back(codePoint); continue; } else { needDots = true; break; } } } if (needDots) { if (!render(String(1, U'.'))) { return false; } const auto& dotGlyph = m_glyphs[m_glyphIndexTable[U'.']]; const int32 dotWidth = dotGlyph.offset.x + dotGlyph.bitmapRect.w; const int32 dotsWidth = dotGlyph.xAdvance * 2 + dotWidth; while (!adjustedText.empty()) { const char32 codePoint = adjustedText.back(); if (codePoint == U'\n') { break; } if (width - penPos.x >= dotsWidth) { break; } const auto& glyphInfo = m_glyphs[m_glyphIndexTable[codePoint]]; penPos.x -= glyphInfo.xAdvance; adjustedText.pop_back(); } if (width - penPos.x >= dotsWidth) { adjustedText.append(U"..."); } } } { Vec2 penPos(area.pos); int32 lineCount = 0; for (const auto& codePoint : adjustedText) { if (codePoint == U'\n') { penPos.x = area.x; penPos.y += m_lineSpacing * lineSpacingScale; ++lineCount; continue; } else if (codePoint == U'\t') { penPos.x += m_tabWidth; continue; } else if (IsControl(codePoint)) { continue; } if (lineCount == 0) { ++lineCount; } const auto& glyphInfo = m_glyphs[m_glyphIndexTable[codePoint]]; m_texture(glyphInfo.bitmapRect).draw(penPos + glyphInfo.offset, color); penPos.x += glyphInfo.xAdvance; } } return !needDots; }
SWTexture* SWFontRenderer::getFontTexture() const { return m_texture(); }
SWTexture* SWSprite::getTexture() const { return m_texture(); }