summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2019-11-12 15:40:14 +0000
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2019-11-12 15:40:14 +0000
commit38d8eaba3e6e17dd39c9e9904852c14c95179783 (patch)
tree0703ba92d765b6d324eefa0d6a0de8fc6910f8cd /indra/llrender
parent63f82fc44b721b0ec437845d41b5a2055a44be68 (diff)
parent78bdf57ad6610b34389226bf941ba736ca0c2225 (diff)
merge
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llfontfreetype.cpp122
-rw-r--r--indra/llrender/llfontfreetype.h9
-rw-r--r--indra/llrender/llfontgl.cpp20
-rw-r--r--indra/llrender/llfontgl.h4
-rw-r--r--indra/llrender/llfontregistry.cpp107
-rw-r--r--indra/llrender/llfontregistry.h4
-rw-r--r--indra/llrender/llrender2dutils.cpp93
-rw-r--r--indra/llrender/llrender2dutils.h45
-rw-r--r--indra/llrender/lluiimage.cpp12
9 files changed, 284 insertions, 132 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index ab668dc192..c41730ebaa 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -157,7 +157,7 @@ void ft_close_cb(FT_Stream stream) {
}
#endif
-BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
+BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
{
// Don't leak face objects. This is also needed to deal with
// changed font file names.
@@ -168,40 +168,8 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
}
int error;
-
#ifdef LL_WINDOWS
- pFileStream = new llifstream(filename, std::ios::binary);
- if (pFileStream->is_open())
- {
- std::streampos beg = pFileStream->tellg();
- pFileStream->seekg(0, std::ios::end);
- std::streampos end = pFileStream->tellg();
- std::size_t file_size = end - beg;
- pFileStream->seekg(0, std::ios::beg);
-
- pFtStream = new LLFT_Stream();
- pFtStream->base = 0;
- pFtStream->pos = 0;
- pFtStream->size = file_size;
- pFtStream->descriptor.pointer = pFileStream;
- pFtStream->read = ft_read_cb;
- pFtStream->close = ft_close_cb;
-
- FT_Open_Args args;
- args.flags = FT_OPEN_STREAM;
- args.stream = (FT_StreamRec*)pFtStream;
-
- error = FT_Open_Face(gFTLibrary,
- &args,
- 0,
- &mFTFace);
- }
- else
- {
- delete pFileStream;
- pFileStream = NULL;
- return FALSE;
- }
+ error = ftOpenFace(filename, face_n);
#else
error = FT_New_Face( gFTLibrary,
filename.c_str(),
@@ -212,11 +180,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (error)
{
#ifdef LL_WINDOWS
- pFileStream->close();
- delete pFileStream;
- delete pFtStream;
- pFileStream = NULL;
- pFtStream = NULL;
+ clearFontStreams();
#endif
return FALSE;
}
@@ -235,11 +199,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
// Clean up freetype libs.
FT_Done_Face(mFTFace);
#ifdef LL_WINDOWS
- pFileStream->close();
- delete pFileStream;
- delete pFtStream;
- pFileStream = NULL;
- pFtStream = NULL;
+ clearFontStreams();
#endif
mFTFace = NULL;
return FALSE;
@@ -285,18 +245,88 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
{
mStyle |= LLFontGL::BOLD;
- mStyle &= ~LLFontGL::NORMAL;
}
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
{
mStyle |= LLFontGL::ITALIC;
- mStyle &= ~LLFontGL::NORMAL;
}
return TRUE;
}
+S32 LLFontFreetype::getNumFaces(const std::string& filename)
+{
+ if (mFTFace)
+ {
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ }
+
+ S32 num_faces = 1;
+
+#ifdef LL_WINDOWS
+ int error = ftOpenFace(filename, 0);
+
+ if (error)
+ {
+ return 0;
+ }
+ else
+ {
+ num_faces = mFTFace->num_faces;
+ }
+
+ FT_Done_Face(mFTFace);
+ clearFontStreams();
+ mFTFace = NULL;
+#endif
+
+ return num_faces;
+}
+
+#ifdef LL_WINDOWS
+S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n)
+{
+ S32 error = -1;
+ pFileStream = new llifstream(filename, std::ios::binary);
+ if (pFileStream->is_open())
+ {
+ std::streampos beg = pFileStream->tellg();
+ pFileStream->seekg(0, std::ios::end);
+ std::streampos end = pFileStream->tellg();
+ std::size_t file_size = end - beg;
+ pFileStream->seekg(0, std::ios::beg);
+
+ pFtStream = new LLFT_Stream();
+ pFtStream->base = 0;
+ pFtStream->pos = 0;
+ pFtStream->size = file_size;
+ pFtStream->descriptor.pointer = pFileStream;
+ pFtStream->read = ft_read_cb;
+ pFtStream->close = ft_close_cb;
+
+ FT_Open_Args args;
+ args.flags = FT_OPEN_STREAM;
+ args.stream = (FT_StreamRec*)pFtStream;
+ error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace);
+ }
+ return error;
+}
+
+void LLFontFreetype::clearFontStreams()
+{
+ if (pFileStream)
+ {
+ pFileStream->close();
+ }
+ delete pFileStream;
+ delete pFtStream;
+ pFileStream = NULL;
+ pFtStream = NULL;
+}
+#endif
+
void LLFontFreetype::setFallbackFonts(const font_vector_t &font)
{
mFallbackFonts = font;
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index aadebf5e70..1afe84e770 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -84,7 +84,14 @@ public:
// is_fallback should be true for fallback fonts that aren't used
// to render directly (Unicode backup, primarily)
- BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback);
+ BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n = 0);
+
+ S32 getNumFaces(const std::string& filename);
+
+#ifdef LL_WINDOWS
+ S32 ftOpenFace(const std::string& filename, S32 face_n);
+ void clearFontStreams();
+#endif
typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 8cd18c5fa1..86a4c35e6d 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -89,14 +89,24 @@ void LLFontGL::destroyGL()
mFontFreetype->destroyGL();
}
-BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
+BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
{
if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
{
mFontFreetype = new LLFontFreetype;
}
- return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);
+ return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback, face_n);
+}
+
+S32 LLFontGL::getNumFaces(const std::string& filename)
+{
+ if (mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
+ {
+ mFontFreetype = new LLFontFreetype;
+ }
+
+ return mFontFreetype->getNumFaces(filename);
}
static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts");
@@ -860,10 +870,6 @@ void LLFontGL::destroyAllGL()
U8 LLFontGL::getStyleFromString(const std::string &style)
{
S32 ret = 0;
- if (style.find("NORMAL") != style.npos)
- {
- ret |= NORMAL;
- }
if (style.find("BOLD") != style.npos)
{
ret |= BOLD;
@@ -883,7 +889,7 @@ U8 LLFontGL::getStyleFromString(const std::string &style)
std::string LLFontGL::getStringFromStyle(U8 style)
{
std::string style_string;
- if (style & NORMAL)
+ if (style == NORMAL)
{
style_string += "|NORMAL";
}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 7d0e53f60f..10891faed9 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -87,7 +87,9 @@ public:
void destroyGL();
- BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback);
+ BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback, S32 face_n = 0);
+
+ S32 getNumFaces(const std::string& filename);
S32 render(const LLWString &text, S32 begin_offset,
const LLRect& rect,
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 3c829596ce..dbe71e2882 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -44,6 +44,8 @@ using std::map;
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc);
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
+const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
+
LLFontDescriptor::LLFontDescriptor():
mStyle(0)
{
@@ -61,6 +63,16 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name,
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
+ const std::string& size,
+ const U8 style,
+ const string_vec_t& file_names,
+ const string_vec_t& ft_collection_listections) :
+ LLFontDescriptor(name, size, style, file_names)
+{
+ mFontCollectionsList = ft_collection_listections;
+}
+
+LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style):
mName(name),
@@ -162,7 +174,7 @@ LLFontDescriptor LLFontDescriptor::normalize() const
if (removeSubString(new_name,"Italic"))
new_style |= LLFontGL::ITALIC;
- return LLFontDescriptor(new_name,new_size,new_style,getFileNames());
+ return LLFontDescriptor(new_name,new_size,new_style,getFileNames(),getFontCollectionsList());
}
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
@@ -213,6 +225,7 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
success = success || init_succ;
}
}
+
//if (success)
// dump();
@@ -260,6 +273,16 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
{
std::string font_file_name = child->getTextContents();
desc.getFileNames().push_back(font_file_name);
+
+ if (child->hasAttribute("load_collection"))
+ {
+ BOOL col = FALSE;
+ child->getAttributeBOOL("load_collection", col);
+ if (col)
+ {
+ desc.getFontCollectionsList().push_back(font_file_name);
+ }
+ }
}
else if (child->hasName("os"))
{
@@ -306,8 +329,15 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
match_file_names.insert(match_file_names.begin(),
desc.getFileNames().begin(),
desc.getFileNames().end());
+
+ string_vec_t collections_list = match_desc->getFontCollectionsList();
+ collections_list.insert(collections_list.begin(),
+ desc.getFontCollectionsList().begin(),
+ desc.getFontCollectionsList().end());
+
LLFontDescriptor new_desc = *match_desc;
new_desc.getFileNames() = match_file_names;
+ new_desc.getFontCollectionsList() = collections_list;
registry->mFontMap.erase(*match_desc);
registry->mFontMap[new_desc] = NULL;
}
@@ -393,6 +423,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
// Build list of font names to look for.
// Files specified for this font come first, followed by those from the default descriptor.
string_vec_t file_names = match_desc->getFileNames();
+ string_vec_t ft_collection_list = match_desc->getFontCollectionsList();
string_vec_t default_file_names;
LLFontDescriptor default_desc("default",s_template_string,0);
const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
@@ -401,6 +432,9 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
file_names.insert(file_names.end(),
match_default_desc->getFileNames().begin(),
match_default_desc->getFileNames().end());
+ ft_collection_list.insert(ft_collection_list.end(),
+ match_default_desc->getFontCollectionsList().begin(),
+ match_default_desc->getFontCollectionsList().end());
}
// Add ultimate fallback list - generated dynamically on linux,
@@ -433,39 +467,62 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
file_name_it != file_names.end();
++file_name_it)
{
- LLFontGL *fontp = new LLFontGL;
- std::string font_path = local_path + *file_name_it;
+ LLFontGL *fontp = NULL;
+ string_vec_t font_paths;
+ font_paths.push_back(local_path + *file_name_it);
+ font_paths.push_back(sys_path + *file_name_it);
+#if LL_DARWIN
+ font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it);
+#endif
+
+ bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end());
// *HACK: Fallback fonts don't render, so we can use that to suppress
// creation of OpenGL textures for test apps. JC
BOOL is_fallback = !is_first_found || !mCreateGLTextures;
F32 extra_scale = (is_fallback)?fallback_scale:1.0;
- if (!fontp->loadFace(font_path, extra_scale * point_size,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback))
+ F32 point_size_scale = extra_scale * point_size;
+ bool is_font_loaded = false;
+ for(string_vec_t::iterator font_paths_it = font_paths.begin();
+ font_paths_it != font_paths.end();
+ ++font_paths_it)
{
- font_path = sys_path + *file_name_it;
-
- if (!fontp->loadFace(font_path, extra_scale * point_size,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback))
+ fontp = new LLFontGL;
+ S32 num_faces = is_ft_collection ? fontp->getNumFaces(*font_paths_it) : 1;
+ for (S32 i = 0; i < num_faces; i++)
{
- LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << " from path " << local_path << LL_ENDL;
- delete fontp;
- fontp = NULL;
+ if (fontp == NULL)
+ {
+ fontp = new LLFontGL;
+ }
+ if (fontp->loadFace(*font_paths_it, point_size_scale,
+ LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback, i))
+ {
+ is_font_loaded = true;
+ if (is_first_found)
+ {
+ result = fontp;
+ is_first_found = false;
+ }
+ else
+ {
+ fontlist.push_back(fontp->mFontFreetype);
+ delete fontp;
+ fontp = NULL;
+ }
+ }
+ else
+ {
+ delete fontp;
+ fontp = NULL;
+ }
}
+ if (is_font_loaded) break;
}
-
- if(fontp)
+ if(!is_font_loaded)
{
- if (is_first_found)
- {
- result = fontp;
- is_first_found = false;
- }
- else
- {
- fontlist.push_back(fontp->mFontFreetype);
- delete fontp;
- fontp = NULL;
- }
+ LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL;
+ delete fontp;
+ fontp = NULL;
}
}
diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h
index 177eb6c8a5..e30c81c630 100644
--- a/indra/llrender/llfontregistry.h
+++ b/indra/llrender/llfontregistry.h
@@ -40,6 +40,7 @@ public:
LLFontDescriptor();
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names);
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names, const string_vec_t& font_collections);
LLFontDescriptor normalize() const;
bool operator<(const LLFontDescriptor& b) const;
@@ -52,6 +53,8 @@ public:
void setSize(const std::string& size) { mSize = size; }
const std::vector<std::string>& getFileNames() const { return mFileNames; }
std::vector<std::string>& getFileNames() { return mFileNames; }
+ const std::vector<std::string>& getFontCollectionsList() const { return mFontCollectionsList; }
+ std::vector<std::string>& getFontCollectionsList() { return mFontCollectionsList; }
const U8 getStyle() const { return mStyle; }
void setStyle(U8 style) { mStyle = style; }
@@ -59,6 +62,7 @@ private:
std::string mName;
std::string mSize;
string_vec_t mFileNames;
+ string_vec_t mFontCollectionsList;
U8 mStyle;
};
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 4e2ebfd51e..4eb0203245 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -46,8 +46,6 @@
// Globals
//
const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
-/*static*/ LLVector2 LLRender2D::sGLScaleFactor(1.f, 1.f);
-/*static*/ LLImageProviderInterface* LLRender2D::sImageProvider = NULL;
//
// Functions
@@ -108,10 +106,11 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixe
top += LLFontGL::sCurOrigin.mY;
gGL.loadUIIdentity();
- gl_rect_2d(llfloor((F32)left * LLRender2D::sGLScaleFactor.mV[VX]) - pixel_offset,
- llfloor((F32)top * LLRender2D::sGLScaleFactor.mV[VY]) + pixel_offset,
- llfloor((F32)right * LLRender2D::sGLScaleFactor.mV[VX]) + pixel_offset,
- llfloor((F32)bottom * LLRender2D::sGLScaleFactor.mV[VY]) - pixel_offset,
+ LLRender2D *r2d_inst = LLRender2D::getInstance();
+ gl_rect_2d(llfloor((F32)left * r2d_inst->mGLScaleFactor.mV[VX]) - pixel_offset,
+ llfloor((F32)top * r2d_inst->mGLScaleFactor.mV[VY]) + pixel_offset,
+ llfloor((F32)right * r2d_inst->mGLScaleFactor.mV[VX]) + pixel_offset,
+ llfloor((F32)bottom * r2d_inst->mGLScaleFactor.mV[VY]) - pixel_offset,
filled);
gGL.popUIMatrix();
}
@@ -800,7 +799,7 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL
}
gGL.end();
- LLRender2D::setLineWidth(1.f);
+ LLRender2D::getInstance()->setLineWidth(1.f);
}
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
@@ -967,7 +966,7 @@ void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
}
else
{ //polygon stipple is deprecated, use "Checker" texture
- LLPointer<LLUIImage> img = LLRender2D::getUIImage("Checker");
+ LLPointer<LLUIImage> img = LLRender2D::getInstance()->getUIImage("Checker");
gGL.getTexUnit(0)->bind(img->getImage());
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
@@ -1567,25 +1566,26 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv
}
-// static
-void LLRender2D::initClass(LLImageProviderInterface* image_provider,
- const LLVector2* scale_factor)
+LLRender2D::LLRender2D(LLImageProviderInterface* image_provider)
{
- sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
- sImageProvider = image_provider;
+ mGLScaleFactor = LLVector2(1.f, 1.f);
+ mImageProvider = image_provider;
+ if(mImageProvider)
+ {
+ mImageProvider->addOnRemovalCallback(resetProvider);
+ }
}
-// static
-void LLRender2D::cleanupClass()
+LLRender2D::~LLRender2D()
{
- if(sImageProvider)
+ if(mImageProvider)
{
- sImageProvider->cleanUp();
+ mImageProvider->cleanUp();
+ mImageProvider->deleteOnRemovalCallback(resetProvider);
}
}
-//static
void LLRender2D::translate(F32 x, F32 y, F32 z)
{
gGL.translateUI(x,y,z);
@@ -1594,14 +1594,12 @@ void LLRender2D::translate(F32 x, F32 y, F32 z)
LLFontGL::sCurDepth += z;
}
-//static
void LLRender2D::pushMatrix()
{
gGL.pushUIMatrix();
LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
}
-//static
void LLRender2D::popMatrix()
{
gGL.popUIMatrix();
@@ -1610,7 +1608,6 @@ void LLRender2D::popMatrix()
LLFontGL::sOriginStack.pop_back();
}
-//static
void LLRender2D::loadIdentity()
{
gGL.loadUIIdentity();
@@ -1619,25 +1616,22 @@ void LLRender2D::loadIdentity()
LLFontGL::sCurDepth = 0.f;
}
-//static
void LLRender2D::setScaleFactor(const LLVector2 &scale_factor)
{
- sGLScaleFactor = scale_factor;
+ mGLScaleFactor = scale_factor;
}
-//static
void LLRender2D::setLineWidth(F32 width)
{
gGL.flush();
- glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
+ glLineWidth(width * lerp(mGLScaleFactor.mV[VX], mGLScaleFactor.mV[VY], 0.5f));
}
-//static
LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
{
- if (sImageProvider)
+ if (mImageProvider)
{
- return sImageProvider->getUIImageByID(image_id, priority);
+ return mImageProvider->getUIImageByID(image_id, priority);
}
else
{
@@ -1645,12 +1639,49 @@ LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 prio
}
}
-//static
LLPointer<LLUIImage> LLRender2D::getUIImage(const std::string& name, S32 priority)
{
- if (!name.empty() && sImageProvider)
- return sImageProvider->getUIImage(name, priority);
+ if (!name.empty() && mImageProvider)
+ return mImageProvider->getUIImage(name, priority);
else
return NULL;
}
+// static
+void LLRender2D::resetProvider()
+{
+ if (LLRender2D::instanceExists)
+ {
+ LLRender2D::getInstance()->mImageProvider = NULL;
+ }
+}
+
+// class LLImageProviderInterface
+
+LLImageProviderInterface::~LLImageProviderInterface()
+{
+ for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end();)
+ {
+ callback_list_t::iterator curiter = iter++;
+ (*curiter)();
+ }
+}
+
+void LLImageProviderInterface::addOnRemovalCallback(callback_t func)
+{
+ if (!func)
+ {
+ return;
+ }
+ mCallbackList.push_back(func);
+}
+
+void LLImageProviderInterface::deleteOnRemovalCallback(callback_t func)
+{
+ callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), func);
+ if (iter != mCallbackList.end())
+ {
+ mCallbackList.erase(iter);
+ }
+}
+
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
index cce3b4ed51..70ab006fd6 100644
--- a/indra/llrender/llrender2dutils.h
+++ b/indra/llrender/llrender2dutils.h
@@ -121,39 +121,54 @@ inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL
class LLImageProviderInterface;
-class LLRender2D
+class LLRender2D : public LLParamSingleton<LLRender2D>
{
+ LLSINGLETON(LLRender2D, LLImageProviderInterface* image_provider);
LOG_CLASS(LLRender2D);
+ ~LLRender2D();
public:
- static void initClass(LLImageProviderInterface* image_provider,
- const LLVector2* scale_factor);
- static void cleanupClass();
+ void pushMatrix();
+ void popMatrix();
+ void loadIdentity();
+ void translate(F32 x, F32 y, F32 z = 0.0f);
- static void pushMatrix();
- static void popMatrix();
- static void loadIdentity();
- static void translate(F32 x, F32 y, F32 z = 0.0f);
+ void setLineWidth(F32 width);
+ void setScaleFactor(const LLVector2& scale_factor);
- static void setLineWidth(F32 width);
- static void setScaleFactor(const LLVector2& scale_factor);
+ LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
- static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
- static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
+ LLVector2 mGLScaleFactor;
+
+protected:
+ // since LLRender2D has no control of image provider's lifecycle
+ // we need a way to tell LLRender2D that provider died and
+ // LLRender2D needs to be updated.
+ static void resetProvider();
- static LLVector2 sGLScaleFactor;
private:
- static LLImageProviderInterface* sImageProvider;
+ LLImageProviderInterface* mImageProvider;
};
class LLImageProviderInterface
{
protected:
LLImageProviderInterface() {};
- virtual ~LLImageProviderInterface() {};
+ virtual ~LLImageProviderInterface();
public:
virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
virtual void cleanUp() = 0;
+
+ // to notify holders when pointer gets deleted
+ typedef void(*callback_t)();
+ void addOnRemovalCallback(callback_t func);
+ void deleteOnRemovalCallback(callback_t func);
+
+private:
+
+ typedef std::list< callback_t > callback_list_t;
+ callback_list_t mCallbackList;
};
diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp
index 5d8f92b2e6..c8337feabb 100644
--- a/indra/llrender/lluiimage.cpp
+++ b/indra/llrender/lluiimage.cpp
@@ -120,12 +120,12 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c
}
}
- LLRender2D::pushMatrix();
+ LLRender2D::getInstance()->pushMatrix();
{
LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
- LLRender2D::translate(rect_origin.mV[VX],
- rect_origin.mV[VY],
- rect_origin.mV[VZ]);
+ LLRender2D::getInstance()->translate(rect_origin.mV[VX],
+ rect_origin.mV[VY],
+ rect_origin.mV[VZ]);
gGL.getTexUnit(0)->bind(getImage());
gGL.color4fv(color.mV);
@@ -142,7 +142,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c
rect.getWidth() * x_axis,
rect.getHeight() * y_axis);
- } LLRender2D::popMatrix();
+ } LLRender2D::getInstance()->popMatrix();
}
@@ -199,7 +199,7 @@ namespace LLInitParam
return;
}
- LLUIImage* imagep = LLRender2D::getUIImage(name());
+ LLUIImage* imagep = LLRender2D::getInstance()->getUIImage(name());
if (imagep)
{
updateValue(imagep);