mirror of
https://github.com/leozide/leocad
synced 2024-12-26 21:58:44 +01:00
Added string cache.
This commit is contained in:
parent
91c421e68b
commit
75ed98b88d
7 changed files with 289 additions and 20 deletions
|
@ -533,6 +533,15 @@ void lcContext::BindTexture2DMS(GLuint Texture)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lcContext::UnbindTexture2D(GLuint Texture)
|
||||||
|
{
|
||||||
|
if (mTexture2D != Texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
mTexture2D = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
|
void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
|
||||||
{
|
{
|
||||||
SetColor(lcVector4(Red, Green, Blue, Alpha));
|
SetColor(lcVector4(Red, Green, Blue, Alpha));
|
||||||
|
|
|
@ -140,6 +140,7 @@ public:
|
||||||
void SetLineWidth(float LineWidth);
|
void SetLineWidth(float LineWidth);
|
||||||
void SetSmoothShading(bool Smooth);
|
void SetSmoothShading(bool Smooth);
|
||||||
void BindTexture2D(GLuint Texture);
|
void BindTexture2D(GLuint Texture);
|
||||||
|
void UnbindTexture2D(GLuint Texture);
|
||||||
void BindTexture2DMS(GLuint Texture);
|
void BindTexture2DMS(GLuint Texture);
|
||||||
|
|
||||||
void SetColor(const lcVector4& Color)
|
void SetColor(const lcVector4& Color)
|
||||||
|
|
229
common/lc_stringcache.cpp
Normal file
229
common/lc_stringcache.cpp
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
#include "lc_global.h"
|
||||||
|
#include "lc_stringcache.h"
|
||||||
|
#include "lc_texture.h"
|
||||||
|
#include "lc_context.h"
|
||||||
|
|
||||||
|
lcStringCache gStringCache;
|
||||||
|
|
||||||
|
lcStringCache::lcStringCache()
|
||||||
|
{
|
||||||
|
mTexture = nullptr;
|
||||||
|
mBuffer = nullptr;
|
||||||
|
mRefCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcStringCache::~lcStringCache()
|
||||||
|
{
|
||||||
|
delete mBuffer;
|
||||||
|
delete mTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcStringCache::AddRef(lcContext* Context)
|
||||||
|
{
|
||||||
|
mRefCount++;
|
||||||
|
|
||||||
|
if (mRefCount == 1)
|
||||||
|
{
|
||||||
|
mTexture = new lcTexture();
|
||||||
|
mTexture->mWidth = 256;
|
||||||
|
mTexture->mHeight = 256;
|
||||||
|
|
||||||
|
glGenTextures(1, &mTexture->mTexture);
|
||||||
|
Context->BindTexture2D(mTexture->mTexture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
mBuffer = new unsigned char[mTexture->mWidth * mTexture->mHeight * 2];
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, mTexture->mWidth, mTexture->mHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, mBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcStringCache::Release(lcContext* Context)
|
||||||
|
{
|
||||||
|
mRefCount--;
|
||||||
|
|
||||||
|
if (mRefCount == 0)
|
||||||
|
{
|
||||||
|
Context->UnbindTexture2D(mTexture->mTexture); // todo: unbind from all contexts
|
||||||
|
|
||||||
|
delete mTexture;
|
||||||
|
mTexture = nullptr;
|
||||||
|
delete mBuffer;
|
||||||
|
mBuffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcStringCache::CacheStrings(lcContext* Context, const QStringList& Strings)
|
||||||
|
{
|
||||||
|
bool Update = false;
|
||||||
|
|
||||||
|
for (const QString& String : Strings)
|
||||||
|
{
|
||||||
|
if (mStrings.find(String) == mStrings.end())
|
||||||
|
{
|
||||||
|
mStrings[String] = lcStringCacheEntry();
|
||||||
|
Update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Update)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QImage Image(128, 128, QImage::Format_RGBA8888);
|
||||||
|
QPainter Painter;
|
||||||
|
QFont Font("Helvetica", 20);
|
||||||
|
int DestX = 0, DestY = 0, DestHeight = 0;
|
||||||
|
memset(mBuffer, 0, mTexture->mWidth * mTexture->mHeight * 2);
|
||||||
|
|
||||||
|
for (auto& Entry : mStrings)
|
||||||
|
{
|
||||||
|
QRect SourceRect;
|
||||||
|
|
||||||
|
Painter.begin(&Image);
|
||||||
|
Painter.fillRect(0, 0, Image.width(), Image.height(), QColor(0, 0, 0));
|
||||||
|
Painter.setBrush(QColor(255, 255, 255));
|
||||||
|
Painter.setPen(QColor(255, 255, 255));
|
||||||
|
Painter.setFont(Font);
|
||||||
|
Painter.drawText(0, 0, Image.width(), Image.height(), 0, Entry.first, &SourceRect);
|
||||||
|
Painter.end();
|
||||||
|
|
||||||
|
if (DestX + SourceRect.width() > mTexture->mWidth)
|
||||||
|
{
|
||||||
|
DestX = 0;
|
||||||
|
DestY += DestHeight;
|
||||||
|
DestHeight = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcStringCacheEntry& String = Entry.second;
|
||||||
|
|
||||||
|
if (SourceRect.width() > mTexture->mWidth || DestY + SourceRect.height() > mTexture->mHeight)
|
||||||
|
{
|
||||||
|
memset(&String, 0, sizeof(String));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String.Top = mTexture->mHeight - DestY - 1;
|
||||||
|
String.Bottom = String.Top - SourceRect.height();
|
||||||
|
String.Left = DestX;
|
||||||
|
String.Right = DestX + SourceRect.width();
|
||||||
|
|
||||||
|
for (int y = SourceRect.top(); y < SourceRect.bottom(); y++)
|
||||||
|
{
|
||||||
|
const unsigned char* Source = Image.constBits() + y * Image.width() * 4;
|
||||||
|
unsigned char* Dest = mBuffer + ((String.Top - y) * mTexture->mWidth + String.Left) * 2;
|
||||||
|
|
||||||
|
for (int x = SourceRect.left(); x < SourceRect.right(); x++)
|
||||||
|
{
|
||||||
|
*Dest = *(Dest + 1) = *Source;
|
||||||
|
Source += 4;
|
||||||
|
Dest += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DestX += SourceRect.width();
|
||||||
|
DestHeight = qMax(DestHeight, SourceRect.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->BindTexture2D(mTexture->mTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, mTexture->mWidth, mTexture->mHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, mBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcStringCache::GetStringDimensions(int* cx, int* cy, const QString& String) const
|
||||||
|
{
|
||||||
|
const auto& Entry = mStrings.find(String);
|
||||||
|
|
||||||
|
if (Entry != mStrings.end())
|
||||||
|
{
|
||||||
|
const lcStringCacheEntry& FontString = Entry->second;
|
||||||
|
*cx = FontString.Right - FontString.Left;
|
||||||
|
*cy = FontString.Top - FontString.Bottom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*cx = *cy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcStringCache::DrawStrings(lcContext* Context, const lcMatrix44* Transforms, const QStringList& Strings) const
|
||||||
|
{
|
||||||
|
float* Verts = (float*)alloca(Strings.size() * 6 * 5 * sizeof(float));
|
||||||
|
float* Buffer = Verts;
|
||||||
|
|
||||||
|
for (int StringIdx = 0; StringIdx < Strings.size(); StringIdx++)
|
||||||
|
{
|
||||||
|
const auto& Entry = mStrings.find(Strings[StringIdx]);
|
||||||
|
|
||||||
|
if (Entry == mStrings.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const lcStringCacheEntry& FontString = Entry->second;
|
||||||
|
|
||||||
|
float u0 = (float)FontString.Left / (float)(mTexture->mWidth - 1);
|
||||||
|
float u1 = (float)FontString.Right / (float)(mTexture->mWidth - 1);
|
||||||
|
float v0 = (float)FontString.Bottom / (float)(mTexture->mHeight - 1);
|
||||||
|
float v1 = (float)FontString.Top / (float)(mTexture->mHeight - 1);
|
||||||
|
|
||||||
|
float Width = FontString.Right - FontString.Left;
|
||||||
|
float Height = FontString.Top - FontString.Bottom;
|
||||||
|
float Left = -Width / 2.0f;
|
||||||
|
float Top = Height / 2.0f;
|
||||||
|
float Z = 0.0f;
|
||||||
|
|
||||||
|
lcVector3 Points[4] =
|
||||||
|
{
|
||||||
|
lcVector3(Left, Top, Z),
|
||||||
|
lcVector3(Left, Top - Height, Z),
|
||||||
|
lcVector3(Left + Width, Top - Height, Z),
|
||||||
|
lcVector3(Left + Width, Top, Z),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int PointIdx = 0; PointIdx < 4; PointIdx++)
|
||||||
|
Points[PointIdx] = lcMul31(Points[PointIdx], Transforms[StringIdx]);
|
||||||
|
|
||||||
|
*Buffer++ = Points[0].x;
|
||||||
|
*Buffer++ = Points[0].y;
|
||||||
|
*Buffer++ = Points[0].z;
|
||||||
|
*Buffer++ = u0;
|
||||||
|
*Buffer++ = v1;
|
||||||
|
|
||||||
|
*Buffer++ = Points[1].x;
|
||||||
|
*Buffer++ = Points[1].y;
|
||||||
|
*Buffer++ = Points[1].z;
|
||||||
|
*Buffer++ = u0;
|
||||||
|
*Buffer++ = v0;
|
||||||
|
|
||||||
|
*Buffer++ = Points[2].x;
|
||||||
|
*Buffer++ = Points[2].y;
|
||||||
|
*Buffer++ = Points[2].z;
|
||||||
|
*Buffer++ = u1;
|
||||||
|
*Buffer++ = v0;
|
||||||
|
|
||||||
|
*Buffer++ = Points[2].x;
|
||||||
|
*Buffer++ = Points[2].y;
|
||||||
|
*Buffer++ = Points[2].z;
|
||||||
|
*Buffer++ = u1;
|
||||||
|
*Buffer++ = v0;
|
||||||
|
|
||||||
|
*Buffer++ = Points[3].x;
|
||||||
|
*Buffer++ = Points[3].y;
|
||||||
|
*Buffer++ = Points[3].z;
|
||||||
|
*Buffer++ = u1;
|
||||||
|
*Buffer++ = v1;
|
||||||
|
|
||||||
|
*Buffer++ = Points[0].x;
|
||||||
|
*Buffer++ = Points[0].y;
|
||||||
|
*Buffer++ = Points[0].z;
|
||||||
|
*Buffer++ = u0;
|
||||||
|
*Buffer++ = v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->SetVertexBufferPointer(Verts);
|
||||||
|
Context->SetVertexFormat(0, 3, 0, 2, 0, false);
|
||||||
|
|
||||||
|
Context->BindTexture2D(mTexture->mTexture);
|
||||||
|
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
Context->DrawPrimitives(GL_TRIANGLES, 0, Strings.size() * 6);
|
||||||
|
}
|
||||||
|
|
29
common/lc_stringcache.h
Normal file
29
common/lc_stringcache.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct lcStringCacheEntry
|
||||||
|
{
|
||||||
|
int Left, Right, Top, Bottom;
|
||||||
|
};
|
||||||
|
|
||||||
|
class lcStringCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
lcStringCache();
|
||||||
|
~lcStringCache();
|
||||||
|
|
||||||
|
void AddRef(lcContext* Context);
|
||||||
|
void Release(lcContext* Context);
|
||||||
|
|
||||||
|
void CacheStrings(lcContext* Context, const QStringList& Strings);
|
||||||
|
void GetStringDimensions(int* cx, int* cy, const QString& String) const;
|
||||||
|
void DrawStrings(lcContext* Context, const lcMatrix44* Transforms, const QStringList& Strings) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
lcTexture* mTexture;
|
||||||
|
unsigned char* mBuffer;
|
||||||
|
int mRefCount;
|
||||||
|
|
||||||
|
std::map<QString, lcStringCacheEntry> mStrings;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern lcStringCache gStringCache;
|
|
@ -2,7 +2,7 @@
|
||||||
#include "lc_viewcube.h"
|
#include "lc_viewcube.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "lc_context.h"
|
#include "lc_context.h"
|
||||||
#include "texfont.h"
|
#include "lc_stringcache.h"
|
||||||
#include "lc_application.h"
|
#include "lc_application.h"
|
||||||
|
|
||||||
//todo: move these
|
//todo: move these
|
||||||
|
@ -185,24 +185,31 @@ void lcViewCube::Draw()
|
||||||
Context->DrawIndexedPrimitives(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, First * 2);
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, First * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, (36 + 144 + 144) * 2);
|
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, (36 + 144 + 144) * 2);
|
||||||
|
|
||||||
Context->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
|
Context->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
|
||||||
Context->BindTexture2D(gTexFont.GetTexture());
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
const char* ViewNames[6] = { "Front", "Back", "Top", "Bottom", "Left", "Right" };
|
QStringList ViewNames =
|
||||||
|
{
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Front"),
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Back"),
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Top"),
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Bottom"),
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Left"),
|
||||||
|
QT_TRANSLATE_NOOP("ViewName", "Right")
|
||||||
|
};
|
||||||
|
|
||||||
int MaxText = 0;
|
int MaxText = 0;
|
||||||
|
|
||||||
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
||||||
{
|
{
|
||||||
int Width, Height;
|
int Width, Height;
|
||||||
gTexFont.GetStringDimensions(&Width, &Height, ViewNames[FaceIdx]);
|
gStringCache.GetStringDimensions(&Width, &Height, ViewNames[FaceIdx]);
|
||||||
if (Width > MaxText)
|
if (Width > MaxText)
|
||||||
MaxText = Width;
|
MaxText = Width;
|
||||||
if (Height > MaxText)
|
if (Height > MaxText)
|
||||||
|
@ -221,23 +228,12 @@ void lcViewCube::Draw()
|
||||||
lcMatrix44(lcVector4(0.0f, -Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(-BoxSize - 0.01f, 0.0f, 0.0f, 1.0f))
|
lcMatrix44(lcVector4(0.0f, -Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(-BoxSize - 0.01f, 0.0f, 0.0f, 1.0f))
|
||||||
};
|
};
|
||||||
|
|
||||||
float TextBuffer[256 * 5 * 3];
|
gStringCache.CacheStrings(Context, ViewNames);
|
||||||
int CharsWritten = 0;
|
gStringCache.DrawStrings(Context, ViewMatrices, ViewNames);
|
||||||
|
|
||||||
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
|
||||||
{
|
|
||||||
const char* ViewName = ViewNames[FaceIdx];
|
|
||||||
gTexFont.GetTriangles(ViewMatrices[FaceIdx], ViewName, TextBuffer + CharsWritten * 2 * 3 * 5);
|
|
||||||
CharsWritten += strlen(ViewName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context->SetVertexBufferPointer(TextBuffer);
|
|
||||||
Context->SetVertexFormat(0, 3, 0, 2, 0, false);
|
|
||||||
|
|
||||||
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
Context->DrawPrimitives(GL_TRIANGLES, 0, CharsWritten * 2 * 3);
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
Context->SetViewport(0, 0, Width, Height);
|
Context->SetViewport(0, 0, Width, Height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,7 @@ SOURCES += common/view.cpp \
|
||||||
common/lc_scene.cpp \
|
common/lc_scene.cpp \
|
||||||
common/lc_selectbycolordialog.cpp \
|
common/lc_selectbycolordialog.cpp \
|
||||||
common/lc_shortcuts.cpp \
|
common/lc_shortcuts.cpp \
|
||||||
|
common/lc_stringcache.cpp \
|
||||||
common/lc_synth.cpp \
|
common/lc_synth.cpp \
|
||||||
common/lc_texture.cpp \
|
common/lc_texture.cpp \
|
||||||
common/lc_viewcube.cpp \
|
common/lc_viewcube.cpp \
|
||||||
|
@ -222,6 +223,7 @@ HEADERS += \
|
||||||
common/lc_scene.h \
|
common/lc_scene.h \
|
||||||
common/lc_selectbycolordialog.h \
|
common/lc_selectbycolordialog.h \
|
||||||
common/lc_shortcuts.h \
|
common/lc_shortcuts.h \
|
||||||
|
common/lc_stringcache.h \
|
||||||
common/lc_synth.h \
|
common/lc_synth.h \
|
||||||
common/lc_texture.h \
|
common/lc_texture.h \
|
||||||
common/lc_viewcube.h \
|
common/lc_viewcube.h \
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "lc_context.h"
|
#include "lc_context.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "texfont.h"
|
#include "texfont.h"
|
||||||
|
#include "lc_stringcache.h"
|
||||||
#include "lc_texture.h"
|
#include "lc_texture.h"
|
||||||
#include "lc_mesh.h"
|
#include "lc_mesh.h"
|
||||||
#include "lc_profile.h"
|
#include "lc_profile.h"
|
||||||
|
@ -94,6 +95,7 @@ lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
|
||||||
widget->MakeCurrent();
|
widget->MakeCurrent();
|
||||||
|
|
||||||
// TODO: Find a better place for the grid texture and font
|
// TODO: Find a better place for the grid texture and font
|
||||||
|
gStringCache.AddRef(widget->mContext);
|
||||||
gTexFont.Load(widget->mContext);
|
gTexFont.Load(widget->mContext);
|
||||||
if (gWidgetList.isEmpty())
|
if (gWidgetList.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -128,6 +130,7 @@ lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
|
||||||
lcQGLWidget::~lcQGLWidget()
|
lcQGLWidget::~lcQGLWidget()
|
||||||
{
|
{
|
||||||
gWidgetList.removeOne(this);
|
gWidgetList.removeOne(this);
|
||||||
|
gStringCache.Release(widget->mContext);
|
||||||
gTexFont.Release();
|
gTexFont.Release();
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
if (gWidgetList.isEmpty())
|
if (gWidgetList.isEmpty())
|
||||||
|
|
Loading…
Reference in a new issue