float CFont::AddStr(CStrAny &sStr, const CVector<2> &vPos, char chPrevious) { ASSERT(IsValid()); if (!sStr.Length()) return 0; UINT uiVerts, uiInds, uiVertSize; uiVerts = sStr.Length() * 4; uiInds = sStr.Length() * 6; CGeometry *pGeom = m_pTextModel->m_pGeometry; uiVertSize = pGeom->m_pInputDesc->GetSize(); ASSERT(uiVertSize == sizeof(TPlainVertex)); if (pGeom->m_pVB->GetSize(0) < (pGeom->m_uiVertices + uiVerts) * uiVertSize) return INVALID_LENGTH; if (pGeom->m_pIB->GetSize(0) < (pGeom->m_uiIndices + uiInds) * sizeof(uint16_t)) return INVALID_LENGTH; TPlainVertex *pVerts; uint16_t *pInds; pVerts = (TPlainVertex *) pGeom->m_pVB->Map(0, CResource::RMF_SYSTEM_ONLY, pGeom->m_uiVertices * uiVertSize, uiVerts * uiVertSize); ASSERT(pVerts); pInds = (uint16_t *) pGeom->m_pIB->Map(0, CResource::RMF_SYSTEM_ONLY, pGeom->m_uiIndices * sizeof(uint16_t), uiInds * sizeof(uint16_t)); ASSERT(pInds); CVector<3> vCur = { vPos.x(), vPos.y() - m_iAscent, 0.5f }, vBoxSize = { 0, (float) m_iHeight, 0 }; int i, iChars = 0; for (i = 0; i < sStr.Length(); i++) { char ch = sStr[i]; if (!m_Chars[(uint8_t) ch].ch) continue; CRect<> rcInTex = GetCharRect(ch); vBoxSize.x() = (float) m_Chars[(uint8_t) ch].iB; vCur.x() += m_Chars[(uint8_t) ch].iA + GetKerning(chPrevious, ch); pVerts[0].vPos.Set(vCur.x(), vCur.y() + vBoxSize.y(), vCur.z()); pVerts[0].vTex = rcInTex.m_vMin; pVerts[1].vPos = vCur; pVerts[1].vTex = rcInTex.GetPoint(0, 1); pVerts[2].vPos = vCur + vBoxSize; pVerts[2].vTex = rcInTex.GetPoint(1, 0); pVerts[3].vPos.Set(vCur.x() + vBoxSize.x(), vCur.y(), vCur.z()); pVerts[3].vTex = rcInTex.m_vMax; pInds[0] = pGeom->m_uiVertices + iChars * 4; pInds[1] = pInds[0] + 1; pInds[2] = pInds[0] + 2; pInds[3] = pInds[0] + 2; pInds[4] = pInds[0] + 1; pInds[5] = pInds[0] + 3; vCur.x() += m_Chars[(uint8_t) ch].iB + m_Chars[(uint8_t) ch].iC; chPrevious = ch; pVerts += 4; pInds += 6; iChars++; } pGeom->m_pIB->Unmap(); pGeom->m_pVB->Unmap(); pGeom->m_uiVertices += iChars * 4; pGeom->m_uiIndices += iChars * 6; return vCur.x() - vPos.x(); }