mirror of
https://github.com/FirestormViewer/phoenix-firestorm.git
synced 2026-08-14 08:53:53 +00:00
Merge branch 'release/2026.02' of https://github.com/secondlife/viewer
# Conflicts: # autobuild.xml # indra/llrender/llfontfreetype.cpp # indra/newview/skins/default/xui/en/fonts.xml # indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
This commit is contained in:
+2
-2
@@ -2756,11 +2756,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9bd007dd70635d85d716ca00484cefa700cdb6f0</string>
|
||||
<string>8de96fd083783b9f4df1d8d7028c8a713a7d7217</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-google-fonts/releases/download/v1.0.0-r2/google_fonts-1.0.0.22606339007-common-22606339007.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-google-fonts/releases/download/v1.0.0-r6/google_fonts-1.0.0.24469773244-common-24469773244.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>common</string>
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
// For some reason, this won't work if it's not wrapped in the ifdef
|
||||
#ifdef FT_FREETYPE_H
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
#endif
|
||||
|
||||
#include "lldir.h"
|
||||
@@ -52,8 +53,6 @@
|
||||
#include "llfontbitmapcache.h"
|
||||
#include "llgl.h"
|
||||
|
||||
#include "llapr.h"
|
||||
|
||||
#define ENABLE_OT_SVG_SUPPORT
|
||||
|
||||
FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
|
||||
@@ -118,6 +117,8 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type)
|
||||
mYBitmapOffset(0), // Offset to the origin in the bitmap
|
||||
mXBearing(0), // Distance from baseline to left in pixels
|
||||
mYBearing(0), // Distance from baseline to top in pixels
|
||||
mLsbDelta(0),
|
||||
mRsbDelta(0),
|
||||
mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
|
||||
{
|
||||
}
|
||||
@@ -133,6 +134,8 @@ LLFontGlyphInfo::LLFontGlyphInfo(const LLFontGlyphInfo& fgi)
|
||||
, mYBitmapOffset(fgi.mYBitmapOffset)
|
||||
, mXBearing(fgi.mXBearing)
|
||||
, mYBearing(fgi.mYBearing)
|
||||
, mLsbDelta(fgi.mLsbDelta)
|
||||
, mRsbDelta(fgi.mRsbDelta)
|
||||
{
|
||||
mBitmapEntry = fgi.mBitmapEntry;
|
||||
}
|
||||
@@ -149,12 +152,6 @@ LLFontFreetype::LLFontFreetype()
|
||||
mStyle(0),
|
||||
mPointSize(0)
|
||||
{
|
||||
// <FS:ND> Set up kerning cache, size is 256x256, the initial cache lines are all null
|
||||
mKerningCache = new F32*[512];
|
||||
|
||||
for (int i = 0; i < 512; ++i)
|
||||
mKerningCache[i] = nullptr;
|
||||
// </FS:ND>
|
||||
}
|
||||
|
||||
|
||||
@@ -171,16 +168,9 @@ LLFontFreetype::~LLFontFreetype()
|
||||
|
||||
delete mFontBitmapCachep;
|
||||
// mFallbackFonts cleaned up by LLPointer destructor
|
||||
|
||||
// <FS:ND> Delete the kerning cache
|
||||
for (S32 i = 0; i < 512; ++i)
|
||||
delete[] mKerningCache[i];
|
||||
|
||||
delete[] mKerningCache;
|
||||
// </FS:ND>
|
||||
}
|
||||
|
||||
bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
|
||||
bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
|
||||
{
|
||||
// Don't leak face objects. This is also needed to deal with
|
||||
// changed font file names.
|
||||
@@ -206,6 +196,18 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
||||
mIsFallback = is_fallback;
|
||||
mHinting = hinting;
|
||||
mFontFlags = flags;
|
||||
mWeight = weight;
|
||||
|
||||
bool variable_font = false;
|
||||
if (weight >= 0)
|
||||
{
|
||||
variable_font = setVariationAxis("wght", static_cast<F32>(weight));
|
||||
|
||||
// For Inter, also set optical size based on point size
|
||||
// This makes text look better at different sizes
|
||||
setVariationAxis("opsz", point_size);
|
||||
}
|
||||
|
||||
F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
|
||||
|
||||
error = FT_Set_Char_Size(mFTFace, /* handle to face object */
|
||||
@@ -267,6 +269,12 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
||||
// Ex: Inter SemiBold doesn't have FT_STYLE_FLAG_BOLD and without this style it would be bolded programmatically.
|
||||
mStyle |= LLFontGL::BOLD;
|
||||
}
|
||||
else if (weight >= 600 && variable_font)
|
||||
{
|
||||
// If the font is heavy enough, consider it bold and avoid programmatic bolding
|
||||
// even if it doesn't have the bold style set.
|
||||
mStyle |= LLFontGL::BOLD;
|
||||
}
|
||||
|
||||
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
|
||||
{
|
||||
@@ -365,46 +373,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
|
||||
|
||||
//llassert(!mIsFallback);
|
||||
LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
|
||||
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
|
||||
// Kern this puppy.
|
||||
LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
|
||||
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
|
||||
|
||||
// <FS:ND> Use cached kerning if possible, only do so for glyphs < 256 for now
|
||||
if (right_glyph < 256 && left_glyph < 256)
|
||||
{
|
||||
const U32 right_glyph_pos = right_glyph * 2 + ((mFTFace->face_flags & FT_FACE_FLAG_SCALABLE) ? 1 : 0);
|
||||
if (mKerningCache[left_glyph] && mKerningCache[left_glyph][right_glyph_pos] < FLT_MAX)
|
||||
return mKerningCache[left_glyph][right_glyph_pos];
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
FT_Vector delta;
|
||||
|
||||
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
|
||||
|
||||
// <FS:ND> Cache kerning if possible, only do so for glyphs < 256 for now
|
||||
if (right_glyph < 256 && left_glyph < 256)
|
||||
{
|
||||
if (!mKerningCache[left_glyph])
|
||||
{
|
||||
mKerningCache[left_glyph] = new F32[512];
|
||||
for (S32 i = 0; i < 512; ++i)
|
||||
mKerningCache[left_glyph][i] = FLT_MAX;
|
||||
}
|
||||
|
||||
// Strided array for right glyph: non-scalable first, scalable version second
|
||||
mKerningCache[left_glyph][right_glyph * 2] = (F32)delta.x ;
|
||||
mKerningCache[left_glyph][right_glyph * 2 + 1] = delta.x * (1.f / 64.f);
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
if (mFTFace->face_flags & FT_FACE_FLAG_SCALABLE)
|
||||
{
|
||||
// Return the X advance
|
||||
return (F32)(delta.x * (1.0 / 64.0));
|
||||
}
|
||||
return (F32)delta.x;
|
||||
return getXKerning(left_glyph_info, right_glyph_info);
|
||||
}
|
||||
|
||||
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
|
||||
@@ -415,41 +387,30 @@ F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LL
|
||||
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
|
||||
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
|
||||
|
||||
// <FS:ND> Use cached kerning if possible, only do so for glyphs < 256 for now
|
||||
if (right_glyph < 256 && left_glyph < 256)
|
||||
{
|
||||
const U32 right_glyph_pos = right_glyph * 2 + ((mFTFace->face_flags & FT_FACE_FLAG_SCALABLE) ? 1 : 0);
|
||||
if (mKerningCache[left_glyph] && mKerningCache[left_glyph][right_glyph_pos] < FLT_MAX)
|
||||
return mKerningCache[left_glyph][right_glyph_pos];
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
FT_Vector delta;
|
||||
|
||||
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
|
||||
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, FT_KERNING_UNFITTED, &delta));
|
||||
|
||||
// <FS:ND> Cache kerning if possible, only do so for glyphs < 256 for now
|
||||
if (right_glyph < 256 && left_glyph < 256)
|
||||
// Apply the FreeType auto-hinter's subpixel side-bearing correction between
|
||||
// adjacent glyphs. When the hinter has shifted the right side of the left
|
||||
// glyph or the left side of the right glyph, (rsb_delta - lsb_delta) is the
|
||||
// sub-pixel nudge that keeps spacing visually even.
|
||||
F32 delta_correction = 0.0f;
|
||||
if (left_glyph_info && right_glyph_info)
|
||||
{
|
||||
if (!mKerningCache[left_glyph])
|
||||
{
|
||||
mKerningCache[left_glyph] = new F32[512];
|
||||
for (S32 i = 0; i < 512; ++i)
|
||||
mKerningCache[left_glyph][i] = FLT_MAX;
|
||||
}
|
||||
|
||||
// Strided array for right glyph: non-scalable first, scalable version second
|
||||
mKerningCache[left_glyph][right_glyph * 2] = (F32)delta.x;
|
||||
mKerningCache[left_glyph][right_glyph * 2 + 1] = delta.x * (1.f / 64.f);
|
||||
// According to FreeType docs, these delta values should only trigger
|
||||
// discrete ±1 pixel adjustments when they cross certain thresholds.
|
||||
// Substructing delta_diff from delta.x doesn't work as well as treating
|
||||
// it as a thresholds
|
||||
S32 delta_diff = left_glyph_info->mRsbDelta - right_glyph_info->mLsbDelta;
|
||||
if (delta_diff > 32)
|
||||
delta_correction = -1.0f;
|
||||
else if (delta_diff < -31)
|
||||
delta_correction = 1.0f;
|
||||
}
|
||||
// </FS:ND>
|
||||
|
||||
if (mFTFace->face_flags & FT_FACE_FLAG_SCALABLE)
|
||||
{
|
||||
// Return the X advance
|
||||
return (F32)(delta.x * (1.0 / 64.0));
|
||||
}
|
||||
return (F32)delta.x;
|
||||
// ft_kerning_unfitted mode always returns 26.6 fixed-point values
|
||||
return (F32)(delta.x * (1.f / 64.f)) + delta_correction;
|
||||
}
|
||||
|
||||
bool LLFontFreetype::hasGlyph(llwchar wch) const
|
||||
@@ -594,6 +555,11 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
|
||||
gi->mHeight = height;
|
||||
gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
|
||||
gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
|
||||
// FreeType fills these when the glyph has been auto-hinted; they describe how
|
||||
// much the hinter nudged the left/right side bearings (in 26.6 pixels). Keep
|
||||
// them so inter-glyph spacing can be corrected in getXKerning().
|
||||
gi->mLsbDelta = (S32)fontp->mFTFace->glyph->lsb_delta;
|
||||
gi->mRsbDelta = (S32)fontp->mFTFace->glyph->rsb_delta;
|
||||
// Convert these from 26.6 units to float pixels.
|
||||
gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
|
||||
gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
|
||||
@@ -771,7 +737,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
|
||||
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
|
||||
{
|
||||
resetBitmapCache();
|
||||
loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0, mHinting, mFontFlags);
|
||||
loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mWeight, mIsFallback, 0, mHinting, mFontFlags);
|
||||
if (!mIsFallback)
|
||||
{
|
||||
// This is the head of the list - need to rebuild ourself and all fallbacks.
|
||||
@@ -939,6 +905,73 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFontFreetype::setVariationAxis(const std::string& axis_tag, F32 value)
|
||||
{
|
||||
if (!mFTFace)
|
||||
return false;
|
||||
|
||||
// Check if this is a variable font
|
||||
FT_MM_Var* master = nullptr;
|
||||
if (FT_Get_MM_Var(mFTFace, &master) != 0)
|
||||
{
|
||||
// Not a variable font - this is not an error, just silently skip
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the axis by tag (e.g., "wght" for weight)
|
||||
FT_UInt axis_index = 0;
|
||||
bool found = false;
|
||||
for (FT_UInt i = 0; i < master->num_axis; i++)
|
||||
{
|
||||
// Compare the 4-byte tag
|
||||
if (master->axis[i].tag == FT_MAKE_TAG(axis_tag[0], axis_tag[1], axis_tag[2], axis_tag[3]))
|
||||
{
|
||||
axis_index = i;
|
||||
found = true;
|
||||
|
||||
// Clamp value to valid range for this axis
|
||||
F32 min_val = master->axis[i].minimum / 65536.0f;
|
||||
F32 max_val = master->axis[i].maximum / 65536.0f;
|
||||
value = llclamp(value, min_val, max_val);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
FT_Done_MM_Var(gFTLibrary, master);
|
||||
LL_WARNS_ONCE("Font") << "Axis '" << axis_tag << "' not found in font: " << mName << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_UInt num_coords = master->num_axis;
|
||||
FT_Fixed* coords = new FT_Fixed[num_coords];
|
||||
|
||||
// Get current coordinates
|
||||
FT_Get_Var_Design_Coordinates(mFTFace, num_coords, coords);
|
||||
|
||||
// Update the specific axis
|
||||
coords[axis_index] = (FT_Fixed)(value * 65536.0f);
|
||||
|
||||
// Set all coordinates
|
||||
int error = FT_Set_Var_Design_Coordinates(mFTFace, num_coords, coords);
|
||||
|
||||
delete[] coords;
|
||||
FT_Done_MM_Var(gFTLibrary, master);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
LL_WARNS() << "Failed to set variation coordinates for " << axis_tag
|
||||
<< " = " << value << " in font: " << mName << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
LL_DEBUGS("Font") << "Set " << axis_tag << " = " << value
|
||||
<< " for font: " << mName << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
namespace ll
|
||||
{
|
||||
|
||||
@@ -88,6 +88,8 @@ struct LLFontGlyphInfo
|
||||
S32 mYBitmapOffset; // Offset to the origin in the bitmap
|
||||
S32 mXBearing; // Distance from baseline to left in pixels
|
||||
S32 mYBearing; // Distance from baseline to top in pixels
|
||||
S32 mLsbDelta; // FreeType subpixel left side bearing delta (26.6 units)
|
||||
S32 mRsbDelta; // FreeType subpixel right side bearing delta (26.6 units)
|
||||
std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
|
||||
};
|
||||
|
||||
@@ -101,7 +103,7 @@ 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, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
|
||||
bool loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
|
||||
@@ -163,6 +165,7 @@ private:
|
||||
void resetBitmapCache();
|
||||
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
|
||||
bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
|
||||
bool setVariationAxis(const std::string& axis_tag, F32 value);
|
||||
bool hasGlyph(llwchar wch) const; // Has a glyph for this character
|
||||
LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
|
||||
LLFontGlyphInfo* addGlyphFromFont(
|
||||
@@ -187,6 +190,7 @@ private:
|
||||
bool mIsFallback;
|
||||
EFontHinting mHinting;
|
||||
S32 mFontFlags;
|
||||
S32 mWeight = -1;
|
||||
typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
|
||||
typedef std::vector<fallback_font_t> fallback_font_vector_t;
|
||||
fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
|
||||
@@ -198,12 +202,6 @@ private:
|
||||
mutable LLFontBitmapCache* mFontBitmapCachep;
|
||||
|
||||
mutable S32 mRenderGlyphCount;
|
||||
|
||||
// <FS:ND> Save X-kerning data, so far only for all glyphs with index small than 256 (to not waste too much memory)
|
||||
// right now it is 256 slots with 256 glyphs each, maybe consider splitting it into smaller slices to use less memory if we
|
||||
// we want to cache 0xFFFF glyphs
|
||||
F32 **mKerningCache;
|
||||
// </FS:ND<
|
||||
};
|
||||
|
||||
#endif // LL_FONTFREETYPE_H
|
||||
|
||||
@@ -90,14 +90,14 @@ void LLFontGL::destroyGL()
|
||||
mFontFreetype->destroyGL();
|
||||
}
|
||||
|
||||
bool LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
|
||||
bool LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
|
||||
{
|
||||
if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
|
||||
{
|
||||
mFontFreetype = new LLFontFreetype;
|
||||
}
|
||||
|
||||
return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n, hinting, flags);
|
||||
return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, weight, is_fallback, face_n, hinting, flags);
|
||||
}
|
||||
|
||||
S32 LLFontGL::getNumFaces(const std::string& filename)
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
|
||||
void destroyGL();
|
||||
|
||||
bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
|
||||
bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
S32 getCacheGeneration() const;
|
||||
|
||||
@@ -214,16 +214,16 @@ LLFontDescriptor LLFontDescriptor::normalize() const
|
||||
return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
|
||||
}
|
||||
|
||||
void LLFontDescriptor::addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, const std::string& char_functor)
|
||||
void LLFontDescriptor::addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor)
|
||||
{
|
||||
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
|
||||
mFontFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, (mCharFunctors.end() != it) ? it->second : nullptr));
|
||||
mFontFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, weight, (mCharFunctors.end() != it) ? it->second : nullptr));
|
||||
}
|
||||
|
||||
void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, const std::string& char_functor)
|
||||
void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor)
|
||||
{
|
||||
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
|
||||
mFontCollectionFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, (mCharFunctors.end() != it) ? it->second : nullptr));
|
||||
mFontCollectionFiles.push_back(LLFontFileInfo(file_name, hinting, flags, size_delta, weight, (mCharFunctors.end() != it) ? it->second : nullptr));
|
||||
}
|
||||
|
||||
LLFontRegistry::LLFontRegistry(bool create_gl_textures, F32 size_mod)
|
||||
@@ -353,6 +353,7 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
|
||||
std::string char_functor;
|
||||
EFontHinting hinting = EFontHinting::FORCE_AUTOHINT;
|
||||
S32 flags = 0;
|
||||
S32 weight = -1;
|
||||
|
||||
if (child->hasAttribute("functor"))
|
||||
{
|
||||
@@ -397,17 +398,22 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
|
||||
child->getAttributeF32("size_delta", size_delta);
|
||||
}
|
||||
|
||||
if (child->hasAttribute("font_weight"))
|
||||
{
|
||||
child->getAttributeS32("font_weight", weight);
|
||||
}
|
||||
|
||||
if (child->hasAttribute("load_collection"))
|
||||
{
|
||||
bool col = false;
|
||||
child->getAttributeBOOL("load_collection", col);
|
||||
if (col)
|
||||
{
|
||||
desc.addFontCollectionFile(font_file_name, hinting, flags, size_delta, char_functor);
|
||||
desc.addFontCollectionFile(font_file_name, hinting, flags, size_delta, weight, char_functor);
|
||||
}
|
||||
}
|
||||
|
||||
desc.addFontFile(font_file_name, hinting, flags, size_delta, char_functor);
|
||||
desc.addFontFile(font_file_name, hinting, flags, size_delta, weight, char_functor);
|
||||
}
|
||||
else if (child->hasName("os"))
|
||||
{
|
||||
@@ -566,7 +572,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
|
||||
// Add ultimate fallback list - generated dynamically on linux,
|
||||
// null elsewhere.
|
||||
std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
|
||||
[](const std::string& file_name) { return LLFontFileInfo(file_name, EFontHinting::FORCE_AUTOHINT, 0, 0.f); });
|
||||
[](const std::string& file_name) { return LLFontFileInfo(file_name, EFontHinting::FORCE_AUTOHINT, 0, 0.f, -1); });
|
||||
|
||||
// Load fonts based on names.
|
||||
if (font_files.empty())
|
||||
@@ -626,7 +632,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
|
||||
fontp = new LLFontGL;
|
||||
}
|
||||
if (fontp->loadFace(font_path, point_size_scale + font_file_it->mSizeDelta,
|
||||
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i, font_file_it->mHinting, font_file_it->mFlags))
|
||||
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, font_file_it->mWeight, is_fallback, i, font_file_it->mHinting, font_file_it->mFlags))
|
||||
{
|
||||
is_font_loaded = true;
|
||||
if (is_first_found)
|
||||
|
||||
@@ -43,21 +43,23 @@ enum class EFontHinting : S32
|
||||
|
||||
struct LLFontFileInfo
|
||||
{
|
||||
LLFontFileInfo(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, const std::function<bool(llwchar)>& char_functor = nullptr)
|
||||
LLFontFileInfo(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::function<bool(llwchar)>& char_functor = nullptr)
|
||||
: FileName(file_name)
|
||||
, CharFunctor(char_functor)
|
||||
, mHinting(hinting)
|
||||
, mFlags(flags)
|
||||
, mSizeDelta(size_delta)
|
||||
, mWeight(weight)
|
||||
{
|
||||
}
|
||||
|
||||
LLFontFileInfo(const LLFontFileInfo& ffi, EFontHinting hinting, S32 flags, F32 size_delta)
|
||||
LLFontFileInfo(const LLFontFileInfo& ffi, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight)
|
||||
: FileName(ffi.FileName)
|
||||
, CharFunctor(ffi.CharFunctor)
|
||||
, mHinting(hinting)
|
||||
, mFlags(flags)
|
||||
, mSizeDelta(size_delta)
|
||||
, mWeight(weight)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,6 +67,7 @@ struct LLFontFileInfo
|
||||
std::function<bool(llwchar)> CharFunctor;
|
||||
EFontHinting mHinting;
|
||||
S32 mFlags;
|
||||
S32 mWeight; // -1 - default, whatever is in the file.
|
||||
|
||||
// Not all fonts are the same size, Ex: dejavu is bigger than inter,
|
||||
// so in some cases we want to adjust relative sizes to make characters
|
||||
@@ -91,10 +94,10 @@ public:
|
||||
const std::string& getSize() const { return mSize; }
|
||||
void setSize(const std::string& size) { mSize = size; }
|
||||
|
||||
void addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, const std::string& char_functor = LLStringUtil::null);
|
||||
void addFontFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor = LLStringUtil::null);
|
||||
const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
|
||||
void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
|
||||
void addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, const std::string& char_functor = LLStringUtil::null);
|
||||
void addFontCollectionFile(const std::string& file_name, EFontHinting hinting, S32 flags, F32 size_delta, S32 weight, const std::string& char_functor = LLStringUtil::null);
|
||||
const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
|
||||
void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<fonts>
|
||||
|
||||
<font
|
||||
name="default"
|
||||
comment="default font files (global fallbacks)">
|
||||
<file load_collection="true" font_hinting="default">Inter_18pt-Regular.ttf</file>
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<file functor="is_emoji_use_color">TwemojiSVG.ttf</file>
|
||||
<file functor="is_emoji_use_bw">NotoEmoji-Regular.ttf</file>
|
||||
@@ -41,7 +41,7 @@
|
||||
<font
|
||||
name="SansSerifBold"
|
||||
comment="Name of bold sans-serif font">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">Inter_18pt-ExtraBold.ttf</file>
|
||||
<file load_collection="true" flags="bold" font_weight="600">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbd.ttf</file>
|
||||
@@ -54,7 +54,7 @@
|
||||
<font
|
||||
name="SansSerif"
|
||||
comment="Name of san-serif font (Truetype file name)">
|
||||
<file load_collection="true" font_hinting="default">Inter_18pt-Regular.ttf</file>
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arial.ttf</file>
|
||||
@@ -68,7 +68,7 @@
|
||||
name="SansSerif"
|
||||
comment="Name of bold sans-serif font"
|
||||
font_style="BOLD">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">Inter_18pt-Bold.ttf</file>
|
||||
<file load_collection="true" flags="bold" font_weight="600">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
</font>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
name="SansSerif"
|
||||
comment="Name of italic sans-serif font"
|
||||
font_style="ITALIC">
|
||||
<file load_collection="true">Inter_18pt-Italic.ttf</file>
|
||||
<file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
|
||||
</font>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
name="SansSerif"
|
||||
comment="Name of bold italic sans-serif font"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file load_collection="true">Inter_18pt-BoldItalic.ttf</file>
|
||||
<file load_collection="true" font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
|
||||
</font>
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
<font
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font">
|
||||
<file font_hinting="default">Inter_18pt-Regular.ttf</file>
|
||||
<file font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arial.ttf</file>
|
||||
@@ -164,7 +164,7 @@
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (bold)"
|
||||
font_style="BOLD">
|
||||
<file font_hinting="default" flags="bold">Inter_18pt-ExtraBold.ttf</file>
|
||||
<file flags="bold" font_weight="800">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbd.ttf</file>
|
||||
@@ -178,7 +178,7 @@
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (italic)"
|
||||
font_style="ITALIC">
|
||||
<file>Inter_18pt-Italic.ttf</file>
|
||||
<file font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>ariali.ttf</file>
|
||||
@@ -192,7 +192,7 @@
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (bold italic)"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file>Inter_18pt-BoldItalic.ttf</file>
|
||||
<file font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbi.ttf</file>
|
||||
@@ -206,7 +206,7 @@
|
||||
name="OverrideTest"
|
||||
comment="Name of font to test overriding">
|
||||
<file>times.ttf</file>
|
||||
<file font_hinting="default">Inter_18pt-Regular.ttf</file>
|
||||
<file font_weight="400">InterVariableFont.ttf</file>
|
||||
</font>
|
||||
|
||||
<font_size
|
||||
|
||||
@@ -3576,8 +3576,9 @@ void uninstall_nsis_if_required()
|
||||
S32 found_minor = 0;
|
||||
S32 found_patch = 0;
|
||||
U64 found_build = 0;
|
||||
std::string nsis_path;
|
||||
|
||||
if (!get_nsis_version(found_major, found_minor, found_patch, found_build))
|
||||
if (!get_nsis_version(found_major, found_minor, found_patch, found_build, nsis_path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3609,7 +3610,7 @@ void uninstall_nsis_if_required()
|
||||
// so there is no point to check build.
|
||||
LL_INFOS() << "Found NSIS install " << found_major << "." << found_minor << "." << found_patch << "." << found_build << LL_ENDL;
|
||||
|
||||
clear_nsis_links();
|
||||
clear_nsis_links(nsis_path);
|
||||
|
||||
LLSD args;
|
||||
args["VERSION"] = llformat("%d.%d.%d", found_major, found_minor, found_patch);
|
||||
|
||||
@@ -343,14 +343,14 @@ static std::wstring get_desktop_path()
|
||||
return L"";
|
||||
}
|
||||
|
||||
static bool create_shortcut(const std::wstring& shortcut_path,
|
||||
static HRESULT create_shortcut(const std::wstring& shortcut_path,
|
||||
const std::wstring& target_path,
|
||||
const std::wstring& arguments,
|
||||
const std::wstring& description,
|
||||
const std::wstring& icon_path)
|
||||
{
|
||||
HRESULT hr = CoInitialize(NULL);
|
||||
if (FAILED(hr)) return false;
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
IShellLinkW* shell_link = nullptr;
|
||||
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
|
||||
@@ -378,7 +378,7 @@ static bool create_shortcut(const std::wstring& shortcut_path,
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
return SUCCEEDED(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void register_protocol_handler(const std::wstring& protocol,
|
||||
@@ -434,9 +434,105 @@ static void register_protocol_handler(const std::wstring& protocol,
|
||||
// </FS:TJ>
|
||||
}
|
||||
|
||||
void clear_nsis_links()
|
||||
static bool get_shortcut_target(const std::wstring& lnk_path, std::wstring& target_path_str)
|
||||
{
|
||||
// Resolve the shortcut to check its target
|
||||
wchar_t target_path[MAX_PATH] = { 0 };
|
||||
HRESULT hr = CoInitialize(NULL);
|
||||
bool res = false;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IShellLinkW* psl = nullptr;
|
||||
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&psl);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IPersistFile* ppf = nullptr;
|
||||
hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ppf->Load(lnk_path.c_str(), STGM_READ);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Resolve() in theory may retarget to a different executable,
|
||||
// but we should be fine as long as folder stays the same,
|
||||
// otherwise we shouldn't clear it.
|
||||
hr = psl->Resolve(NULL, SLR_NO_UI | SLR_NOUPDATE | SLR_ANY_MATCH);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = psl->GetPath(target_path, MAX_PATH, nullptr, 0);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
target_path_str = std::wstring(target_path);
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ppf->Release();
|
||||
}
|
||||
psl->Release();
|
||||
}
|
||||
CoUninitialize();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool paths_are_equal(const std::wstring& path1, const std::wstring& path2)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::error_code ec1, ec2;
|
||||
std::filesystem::path p1(path1);
|
||||
std::filesystem::path p2(path2);
|
||||
|
||||
// Get canonical (absolute, normalized) paths
|
||||
auto canonical1 = std::filesystem::canonical(p1, ec1);
|
||||
auto canonical2 = std::filesystem::canonical(p2, ec2);
|
||||
|
||||
// If either path doesn't exist, fall back to string comparison
|
||||
if (ec1 || ec2)
|
||||
{
|
||||
// Normalize case for comparison
|
||||
std::wstring lower1 = path1;
|
||||
std::wstring lower2 = path2;
|
||||
std::transform(lower1.begin(), lower1.end(), lower1.begin(), ::towlower);
|
||||
std::transform(lower2.begin(), lower2.end(), lower2.begin(), ::towlower);
|
||||
while (!lower1.empty() && (lower1.back() == L'\\' || lower1.back() == L'/'))
|
||||
{
|
||||
lower1.pop_back();
|
||||
}
|
||||
while (!lower2.empty() && (lower2.back() == L'\\' || lower2.back() == L'/'))
|
||||
{
|
||||
lower2.pop_back();
|
||||
}
|
||||
return lower1 == lower2;
|
||||
}
|
||||
|
||||
// Use filesystem::equivalent which handles all path variations
|
||||
return std::filesystem::equivalent(canonical1, canonical2, ec1);
|
||||
}
|
||||
catch (const std::filesystem::filesystem_error&)
|
||||
{
|
||||
// Fallback to case-insensitive string comparison
|
||||
std::wstring lower1 = path1;
|
||||
std::wstring lower2 = path2;
|
||||
std::transform(lower1.begin(), lower1.end(), lower1.begin(), ::towlower);
|
||||
std::transform(lower2.begin(), lower2.end(), lower2.begin(), ::towlower);
|
||||
while (!lower1.empty() && (lower1.back() == L'\\' || lower1.back() == L'/'))
|
||||
{
|
||||
lower1.pop_back();
|
||||
}
|
||||
while (!lower2.empty() && (lower2.back() == L'\\' || lower2.back() == L'/'))
|
||||
{
|
||||
lower2.pop_back();
|
||||
}
|
||||
return lower1 == lower2;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_nsis_links(const std::string& nsis_folder_path)
|
||||
{
|
||||
wchar_t path[MAX_PATH];
|
||||
std::wstring app_name = get_app_name();
|
||||
|
||||
// 1. The 'start' shortcuts set by nsis would be global, like app shortcut:
|
||||
// C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Second Life Viewer\Second Life Viewer.lnk
|
||||
@@ -444,7 +540,7 @@ void clear_nsis_links()
|
||||
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, path)))
|
||||
{
|
||||
std::wstring start_menu_path = path;
|
||||
std::wstring folder_path = start_menu_path + L"\\" + get_app_name();
|
||||
std::wstring folder_path = start_menu_path + L"\\" + app_name;
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::path dir(folder_path);
|
||||
@@ -460,11 +556,11 @@ void clear_nsis_links()
|
||||
}
|
||||
|
||||
// 2. Desktop link, also a global one.
|
||||
// C:\Users\Public\Desktop
|
||||
// C:\Users\Public\Desktop\Second Life Viewer.lnk
|
||||
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, path)))
|
||||
{
|
||||
std::wstring desktop_path = path;
|
||||
std::wstring shortcut_path = desktop_path + L"\\" + get_app_name() + L".lnk";
|
||||
std::wstring shortcut_path = desktop_path + L"\\" + app_name + L".lnk";
|
||||
if (!DeleteFileW(shortcut_path.c_str()))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
@@ -476,6 +572,70 @@ void clear_nsis_links()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Taskbar link, which is user-specific and located at:
|
||||
// %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Second Life.lnk
|
||||
// Note that it can be a link to velopack already, but since
|
||||
// we aren't removing, but recreating, it shouldn't be an issue.
|
||||
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path)))
|
||||
{
|
||||
std::wstring taskbar_path = path;
|
||||
// Hardcoded, because this name is the default window name and isn't going to change in NSIS
|
||||
taskbar_path += L"\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar\\Second Life.lnk";
|
||||
|
||||
if (PathFileExistsW(taskbar_path.c_str()))
|
||||
{
|
||||
// First try to overwrite shortcut
|
||||
std::wstring current_exe = ll_convert<std::wstring>(gDirUtilp->getExecutablePathAndName());
|
||||
|
||||
HRESULT hr = create_shortcut(taskbar_path, current_exe, L"", app_name, current_exe);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LL_WARNS("Velopack") << "Failed to update taskbar shortcut, error " << std::hex << hr << LL_ENDL;
|
||||
// Try deleting and if possible recreating separately. We should not leave hanging shortcuts behind.
|
||||
// It is not warranted that the shortcut points to NSIS, so check the destination first.
|
||||
std::wstring target_path;
|
||||
if (get_shortcut_target(taskbar_path, target_path))
|
||||
{
|
||||
// Strip the filename part to get just the folder path
|
||||
std::filesystem::path trim_path(target_path);
|
||||
if (trim_path.has_filename())
|
||||
{
|
||||
target_path = trim_path.parent_path().wstring();
|
||||
}
|
||||
std::wstring nsis_path_w = ll_convert<std::wstring>(nsis_folder_path);
|
||||
if (paths_are_equal(nsis_path_w, target_path))
|
||||
{
|
||||
if (!DeleteFileW(taskbar_path.c_str()))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
LL_WARNS("Velopack") << "Failed to delete NSIS taskbar shortcut: "
|
||||
<< ll_convert_wide_to_string(taskbar_path)
|
||||
<< " (error: " << error << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deleted user created link, recreate it with new target if possible.
|
||||
LL_INFOS("Velopack") << "Updating taskbar shortcut to point to current exe" << LL_ENDL;
|
||||
HRESULT hr = create_shortcut(taskbar_path, current_exe, L"", app_name, current_exe);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LL_WARNS("Velopack") << "Failed to re-create taskbar shortcut, error: " << std::hex << hr << ", NSIS shortcut was removed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("Velopack") << "Successfully updated taskbar shortcut to point to current exe" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
// else user didn't create a taskbar shortcut.
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_version(const wchar_t* version_str, int& major, int& minor, int& patch, uint64_t& build)
|
||||
@@ -491,7 +651,8 @@ bool get_nsis_version(
|
||||
int& nsis_major,
|
||||
int& nsis_minor,
|
||||
int& nsis_patch,
|
||||
uint64_t& nsis_build)
|
||||
uint64_t& nsis_build,
|
||||
std::string& nsis_path)
|
||||
{
|
||||
// Test for presence of NSIS viewer registration, then
|
||||
// attempt to read uninstall info
|
||||
@@ -544,12 +705,21 @@ bool get_nsis_version(
|
||||
}
|
||||
std::error_code ec;
|
||||
std::filesystem::path path(path_buffer);
|
||||
// check if uninstaller exists
|
||||
if (!std::filesystem::exists(path, ec))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Todo: check codesigning?
|
||||
// We found a valid NSIS installation, trim the path to get the folder
|
||||
wchar_t* pos = wcsstr(path_buffer, L"uninst.exe");
|
||||
if (pos)
|
||||
{
|
||||
// Trim uninst.exe from the path by setting null terminator before it
|
||||
*pos = L'\0';
|
||||
}
|
||||
// Note that it has a trailing backslash.
|
||||
nsis_path = ll_convert_wide_to_string(path_buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -46,12 +46,13 @@ void velopack_set_progress_callback(std::function<void(int)> callback);
|
||||
void velopack_cleanup();
|
||||
|
||||
#if LL_WINDOWS
|
||||
void clear_nsis_links();
|
||||
void clear_nsis_links(const std::string& nsis_folder_path);
|
||||
bool get_nsis_version(
|
||||
int& nsis_major,
|
||||
int& nsis_minor,
|
||||
int& nsis_patch,
|
||||
uint64_t& nsis_build);
|
||||
uint64_t& nsis_build,
|
||||
std::string& nsis_folder_path);
|
||||
#endif
|
||||
|
||||
#endif // LL_VELOPACK
|
||||
|
||||
@@ -472,10 +472,6 @@ void LLVoiceChannelGroup::activate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mic default state is OFF on initiating/joining Ad-Hoc/Group calls. It's on for P2P using the AdHoc infra.
|
||||
|
||||
LLVoiceClient::getInstance()->setUserPTTState(mIsP2P);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,6 +530,10 @@ void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
|
||||
case STATUS_JOINED:
|
||||
mRetries = 3;
|
||||
mIsRetrying = false;
|
||||
|
||||
// Mic default state is OFF on initiating/joining Ad-Hoc/Group calls. It's on for P2P using the AdHoc infra.
|
||||
LLVoiceClient::getInstance()->setUserPTTState(mIsP2P);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "llrootview.h"
|
||||
#include "llsdutil.h"
|
||||
#include "stringize.h"
|
||||
#include "llclipboard.h"
|
||||
#include "lleditmenuhandler.h"
|
||||
#include <functional>
|
||||
#include <typeinfo>
|
||||
#include <map>
|
||||
@@ -107,6 +109,10 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter&
|
||||
"Given an integer number of [\"clicks\"], inject the requested mouse scroll event.\n"
|
||||
"(positive clicks moves downward through typical content)",
|
||||
&LLWindowListener::mouseScroll);
|
||||
add("pasteText",
|
||||
"Paste specified [\"text\"] into the current edit field\n"
|
||||
"Optional [\"path\"] specifies target UI element (must be focusable).",
|
||||
&LLWindowListener::pasteText);
|
||||
}
|
||||
|
||||
template <typename MAPPED>
|
||||
@@ -521,3 +527,60 @@ void LLWindowListener::mouseScroll(LLSD const & request)
|
||||
|
||||
mWindow->handleScrollWheel(NULL, clicks);
|
||||
}
|
||||
|
||||
void LLWindowListener::pasteText(LLSD const & evt)
|
||||
{
|
||||
Response response(LLSD(), evt);
|
||||
|
||||
if (!evt.has("text"))
|
||||
{
|
||||
response.error(STRINGIZE(evt["op"].asString() << " request did not provide required \"text\" parameter"));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string text_to_paste = evt["text"].asString();
|
||||
if (evt.has("path"))
|
||||
{
|
||||
std::string path(evt["path"]);
|
||||
LLView* target_view = LLUI::getInstance()->resolvePath(LLUI::getInstance()->getRootView(), path);
|
||||
if (!target_view)
|
||||
{
|
||||
response.error(STRINGIZE(evt["op"].asString() << " request specified invalid \"path\": " << path));
|
||||
return;
|
||||
}
|
||||
else if(!target_view->isAvailable())
|
||||
{
|
||||
response.error(STRINGIZE("Target view specified by \"path\": " << path << " is not visible"));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Focus the target view
|
||||
gFocusMgr.setKeyboardFocus(target_view);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if edit menu handler is available
|
||||
if (!LLEditMenuHandler::gEditMenuHandler)
|
||||
{
|
||||
response.error(STRINGIZE(evt["op"].asString() << " request failed: no edit menu handler available"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Save current clipboard contents
|
||||
LLWString saved_clipboard;
|
||||
LLClipboard::instance().pasteFromClipboard(saved_clipboard);
|
||||
|
||||
LLClipboard::instance().copyToClipboard(utf8str_to_wstring(text_to_paste), 0, static_cast<S32>(text_to_paste.size()));
|
||||
LLEditMenuHandler::gEditMenuHandler->paste();
|
||||
|
||||
// Restore original clipboard contents if there were any
|
||||
if (!saved_clipboard.empty())
|
||||
{
|
||||
LLClipboard::instance().copyToClipboard(saved_clipboard, 0, static_cast<S32>(saved_clipboard.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLClipboard::instance().reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
void mouseUp(LLSD const & evt);
|
||||
void mouseMove(LLSD const & evt);
|
||||
void mouseScroll(LLSD const & evt);
|
||||
void pasteText(LLSD const & evt);
|
||||
|
||||
private:
|
||||
LLViewerWindow * mWindow;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<fonts>
|
||||
|
||||
<font name="default" comment="default font files (global fallbacks)">
|
||||
<file>DejaVuSans.ttf</file>
|
||||
<file functor="is_emoji_use_color">TwemojiSVG.ttf</file>
|
||||
<file functor="is_emoji_use_bw">NotoEmoji-Regular.ttf</file>
|
||||
<font
|
||||
name="default"
|
||||
comment="default font files (global fallbacks)">
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<file functor="is_emoji">TwemojiSVG.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>MSNeoGothic.ttf</file>
|
||||
<file>meiryo.TTC</file>
|
||||
<file>MSGOTHIC.TTC</file>
|
||||
<file>gulim.ttc</file>
|
||||
@@ -14,6 +15,7 @@
|
||||
<file>ArialUni.ttf</file>
|
||||
<file>msyh.ttc</file>
|
||||
<file load_collection="true">Cambria.ttc</file>
|
||||
<file>malgun.ttf</file>
|
||||
<file>micross.ttf</file>
|
||||
</os>
|
||||
<os name="Mac">
|
||||
@@ -32,9 +34,11 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="SansSerifBold"
|
||||
comment="Name of bold sans-serif font">
|
||||
<file>DejaVuSans-Bold.ttf</file>
|
||||
<font
|
||||
name="SansSerifBold"
|
||||
comment="Name of bold sans-serif font">
|
||||
<file load_collection="true" flags="bold" font_weight="600">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbd.ttf</file>
|
||||
</os>
|
||||
@@ -43,8 +47,11 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
|
||||
<file>DejaVuSans.ttf</file>
|
||||
<font
|
||||
name="SansSerif"
|
||||
comment="Name of san-serif font (Truetype file name)">
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arial.ttf</file>
|
||||
</os>
|
||||
@@ -53,36 +60,38 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="SansSerif"
|
||||
comment="Name of bold sans-serif font"
|
||||
font_style="BOLD">
|
||||
<file>DejaVuSans-Bold.ttf</file>
|
||||
<font
|
||||
name="SansSerif"
|
||||
comment="Name of bold sans-serif font"
|
||||
font_style="BOLD">
|
||||
<file load_collection="true" flags="bold" font_weight="600">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="SansSerif"
|
||||
comment="Name of italic sans-serif font"
|
||||
font_style="ITALIC">
|
||||
<file>DejaVuSans-Oblique.ttf</file>
|
||||
<font
|
||||
name="SansSerif"
|
||||
comment="Name of italic sans-serif font"
|
||||
font_style="ITALIC">
|
||||
<file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="SansSerif"
|
||||
comment="Name of bold italic sans-serif font"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file>DejaVuSans-BoldOblique.ttf</file>
|
||||
<font
|
||||
name="SansSerif"
|
||||
comment="Name of bold italic sans-serif font"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file load_collection="true" font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="Emoji"
|
||||
comment="Name of emoji font">
|
||||
<file>TwemojiSVG.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="EmojiBW"
|
||||
comment="Name of Black and White emoji font">
|
||||
<file>NotoEmoji-Regular.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="Monospace"
|
||||
comment="Name of monospace font">
|
||||
|
||||
<font
|
||||
name="Monospace"
|
||||
comment="Name of monospace font">
|
||||
<file>DejaVuSansMono.ttf</file>
|
||||
</font>
|
||||
|
||||
@@ -109,9 +118,11 @@
|
||||
<file>DejaVuSans-BoldOblique.ttf</file>
|
||||
</font>
|
||||
|
||||
<font name="Helvetica"
|
||||
comment="Name of Helvetica font">
|
||||
<file>DejaVuSans.ttf</file>
|
||||
<font
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font">
|
||||
<file font_weight="400">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arial.ttf</file>
|
||||
</os>
|
||||
@@ -120,10 +131,12 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="Helvetica"
|
||||
comment="Name of Helvetica font (bold)"
|
||||
font_style="BOLD">
|
||||
<file>DejaVuSans-Bold.ttf</file>
|
||||
<font
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (bold)"
|
||||
font_style="BOLD">
|
||||
<file flags="bold" font_weight="800">InterVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Bold.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbd.ttf</file>
|
||||
</os>
|
||||
@@ -132,10 +145,12 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="Helvetica"
|
||||
comment="Name of Helvetica font (italic)"
|
||||
font_style="ITALIC">
|
||||
<file>DejaVuSans-Oblique.ttf</file>
|
||||
<font
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (italic)"
|
||||
font_style="ITALIC">
|
||||
<file font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-Oblique.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>ariali.ttf</file>
|
||||
</os>
|
||||
@@ -144,10 +159,12 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="Helvetica"
|
||||
comment="Name of Helvetica font (bold italic)"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file>DejaVuSans-BoldOblique.ttf</file>
|
||||
<font
|
||||
name="Helvetica"
|
||||
comment="Name of Helvetica font (bold italic)"
|
||||
font_style="BOLD|ITALIC">
|
||||
<file font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
<file size_delta="-0.5">DejaVuSans-BoldOblique.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>arialbi.ttf</file>
|
||||
</os>
|
||||
@@ -156,33 +173,38 @@
|
||||
</os>
|
||||
</font>
|
||||
|
||||
<font name="OverrideTest"
|
||||
comment="Name of font to test overriding">
|
||||
<font
|
||||
name="OverrideTest"
|
||||
comment="Name of font to test overriding">
|
||||
<file>times.ttf</file>
|
||||
<file>DejaVuSans.ttf</file>
|
||||
<file font_weight="400">InterVariableFont.ttf</file>
|
||||
</font>
|
||||
|
||||
<font_size name="Monospace"
|
||||
comment="Size for monospaced font (points, or 1/72 of an inch)"
|
||||
size="8.0"
|
||||
/>
|
||||
comment="Size for monospaced font (points, or 1/72 of an inch)"
|
||||
size="8.0"
|
||||
/>
|
||||
<font_size name="Huge"
|
||||
comment="Size of huge font (points, or 1/72 of an inch)"
|
||||
size="16.0"
|
||||
/>
|
||||
comment="Size of huge font (points, or 1/72 of an inch)"
|
||||
size="16.0"
|
||||
/>
|
||||
<font_size name="Large"
|
||||
comment="Size of large font (points, or 1/72 of an inch)"
|
||||
size="10.6"
|
||||
/>
|
||||
comment="Size of large font (points, or 1/72 of an inch)"
|
||||
size="11.0"
|
||||
/>
|
||||
<font_size name="Medium"
|
||||
comment="Size of medium font (points, or 1/72 of an inch)"
|
||||
size="8.6"
|
||||
/>
|
||||
comment="Size of medium font (points, or 1/72 of an inch)"
|
||||
size="10"
|
||||
/>
|
||||
<font_size name="Small"
|
||||
comment="Size of small font (points, or 1/72 of an inch)"
|
||||
size="7.6"
|
||||
/>
|
||||
<font_size name="SmallLSL"
|
||||
comment="Size of small font (points, or 1/72 of an inch)"
|
||||
size="9"
|
||||
/>
|
||||
<font_size name="LSmall"
|
||||
comment="Legacy size of small font (points, or 1/72 of an inch)"
|
||||
size="7.6"
|
||||
/>
|
||||
<font_size name="SmallLSL"
|
||||
comment="Size of small font for LSL editor (points, or 1/72 of an inch)"
|
||||
size="7"
|
||||
/>
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
<file>
|
||||
NotoSansCJKjp-SemiBold.otf
|
||||
</file>
|
||||
<file load_collection="true" font_hinting="default">
|
||||
Inter_18pt-Regular.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file load_collection="true">
|
||||
YuGothM.ttc
|
||||
@@ -82,9 +80,7 @@
|
||||
<file>
|
||||
NotoSansCJKjp-Bold.otf
|
||||
</file>
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBold.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="800" flags="bold">InterVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file load_collection="true">
|
||||
YuGothB.ttc
|
||||
@@ -104,11 +100,9 @@
|
||||
</font>
|
||||
<font name="SansSerif" comment="Name of san-serif font (Truetype file name)">
|
||||
<file>
|
||||
NotoSansCJKjp-Bold.otf
|
||||
NotoSansCJKjp-SemiBold.otf
|
||||
</file>
|
||||
<file load_collection="true" font_hinting="default">
|
||||
Inter_18pt-Regular.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>
|
||||
arial.ttf
|
||||
@@ -121,19 +115,13 @@
|
||||
</os>
|
||||
</font>
|
||||
<font name="SansSerif" comment="Name of bold sans-serif font" font_style="BOLD">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBold.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="800" flags="bold">InterVariableFont.ttf</file>
|
||||
</font>
|
||||
<font name="SansSerif" comment="Name of italic sans-serif font" font_style="ITALIC">
|
||||
<file load_collection="true">
|
||||
Inter_18pt-Italic.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
</font>
|
||||
<font name="SansSerif" comment="Name of bold italic sans-serif font" font_style="BOLD|ITALIC">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBoldItalic.ttf
|
||||
</file>
|
||||
<file load_collection="true" flags="bold" font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
</font>
|
||||
<font name="Monospace" comment="Name of monospace font">
|
||||
<file>
|
||||
@@ -144,29 +132,25 @@
|
||||
</file>
|
||||
</font>
|
||||
<font name="DejaVu" comment="Name of DejaVu font">
|
||||
<file load_collection="true" font_hinting="default">
|
||||
Inter_18pt-Regular.ttf
|
||||
</file>
|
||||
<file>DejaVuSans.ttf</file>
|
||||
</font>
|
||||
<font name="DejaVu" comment="Name of DejaVu font (bold)" font_style="BOLD">
|
||||
<file load_collection="true" font_hinting="force_auto" flags="bold">
|
||||
Inter_18pt-SemiBold.ttf
|
||||
<file>
|
||||
DejaVuSans-Bold.ttf
|
||||
</file>
|
||||
</font>
|
||||
<font name="DejaVu" comment="Name of DejaVu font (italic)" font_style="ITALIC">
|
||||
<file load_collection="true">
|
||||
Inter_18pt-Italic.ttf
|
||||
<file>
|
||||
DejaVuSans-Oblique.ttf
|
||||
</file>
|
||||
</font>
|
||||
<font name="DejaVu" comment="Name of DejaVu font (bold italic)" font_style="BOLD|ITALIC">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBoldItalic.ttf
|
||||
<file>
|
||||
DejaVuSans-BoldOblique.ttf
|
||||
</file>
|
||||
</font>
|
||||
<font name="Helvetica" comment="Name of Helvetica font">
|
||||
<file load_collection="true" font_hinting="default">
|
||||
Inter_18pt-Regular.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="400">InterVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>
|
||||
arial.ttf
|
||||
@@ -179,9 +163,7 @@
|
||||
</os>
|
||||
</font>
|
||||
<font name="Helvetica" comment="Name of Helvetica font (bold)" font_style="BOLD">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBold.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="800" flags="bold">InterVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>
|
||||
arialbd.ttf
|
||||
@@ -194,9 +176,7 @@
|
||||
</os>
|
||||
</font>
|
||||
<font name="Helvetica" comment="Name of Helvetica font (italic)" font_style="ITALIC">
|
||||
<file load_collection="true">
|
||||
Inter_18pt-Italic.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_weight="400">InterItalicVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>
|
||||
ariali.ttf
|
||||
@@ -209,9 +189,7 @@
|
||||
</os>
|
||||
</font>
|
||||
<font name="Helvetica" comment="Name of Helvetica font (bold italic)" font_style="BOLD|ITALIC">
|
||||
<file load_collection="true" font_hinting="default" flags="bold">
|
||||
Inter_18pt-SemiBoldItalic.ttf
|
||||
</file>
|
||||
<file load_collection="true" flags="bold" font_weight="800">InterItalicVariableFont.ttf</file>
|
||||
<os name="Windows">
|
||||
<file>
|
||||
arialbi.ttf
|
||||
@@ -227,9 +205,7 @@
|
||||
<file>
|
||||
times.ttf
|
||||
</file>
|
||||
<file load_collection="true" font_hinting="default">
|
||||
Inter_18pt-Regular.ttf
|
||||
</file>
|
||||
<file font_weight="400">InterVariableFont.ttf</file>
|
||||
</font>
|
||||
<font_size name="Monospace" comment="Size for monospaced font (points, or 1/72 of an inch)" size="8.0"/>
|
||||
<font_size name="Huge" comment="Size of huge font (points, or 1/72 of an inch)" size="16.0"/>
|
||||
|
||||
Reference in New Issue
Block a user