GLEGram 12.5 — Initial public release

Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
This commit is contained in:
Leeksov
2026-04-06 09:48:12 +03:00
commit 4647310322
39685 changed files with 11052678 additions and 0 deletions
@@ -0,0 +1,65 @@
#ifndef PassThroughOutputNode_hpp
#define PassThroughOutputNode_hpp
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/HasRenderUpdates.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/HasUpdate.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/Protocols/NodeOutput.hpp"
namespace lottie {
class PassThroughOutputNode: virtual public NodeOutput, virtual public HasRenderUpdates, virtual public HasUpdate {
public:
PassThroughOutputNode(std::shared_ptr<NodeOutput> parent) :
_parent(parent) {
}
virtual ~PassThroughOutputNode() = default;
virtual std::shared_ptr<NodeOutput> parent() override {
return _parent;
}
virtual bool isEnabled() const override {
return _isEnabled;
}
virtual void setIsEnabled(bool isEnabled) override {
_isEnabled = isEnabled;
}
virtual bool hasUpdate() override {
return _hasUpdate;
}
void setHasUpdate(bool hasUpdate) {
_hasUpdate = hasUpdate;
}
virtual bool hasOutputUpdates(float forFrame) override {
/// Changes to this node do not affect downstream nodes.
bool parentUpdate = false;
if (_parent) {
parentUpdate = _parent->hasOutputUpdates(forFrame);
}
/// Changes to upstream nodes do, however, affect this nodes state.
_hasUpdate = _hasUpdate || parentUpdate;
return parentUpdate;
}
virtual bool hasRenderUpdates(float forFrame) override {
/// Return true if there are upstream updates or if this node has updates
bool upstreamUpdates = false;
if (_parent) {
upstreamUpdates = _parent->hasOutputUpdates(forFrame);
}
_hasUpdate = _hasUpdate || upstreamUpdates;
return _hasUpdate;
}
private:
std::shared_ptr<NodeOutput> _parent;
bool _hasUpdate = false;
bool _isEnabled = true;
};
}
#endif /* PassThroughOutputNode_hpp */
@@ -0,0 +1,33 @@
#ifndef StrokeNode_hpp
#define StrokeNode_hpp
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.hpp"
#include "Lottie/Private/Model/ShapeItems/Stroke.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/KeyframeInterpolator.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/SingleValueProvider.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/DashPatternInterpolator.hpp"
namespace lottie {
class StrokeShapeDashConfiguration {
public:
StrokeShapeDashConfiguration(std::vector<DashElement> const &elements) {
for (const auto &dash : elements) {
if (dash.type == DashElementType::Offset) {
dashPhase = dash.value.keyframes;
} else {
dashPatterns.push_back(dash.value.keyframes);
}
}
}
public:
std::vector<std::vector<Keyframe<Vector1D>>> dashPatterns;
std::vector<Keyframe<Vector1D>> dashPhase;
};
}
#endif /* StrokeNode_hpp */
@@ -0,0 +1,361 @@
#ifndef TextAnimatorNode_hpp
#define TextAnimatorNode_hpp
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.hpp"
#include "Lottie/Private/Model/Text/TextAnimator.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/NodeProperty.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/NodeProperties/ValueProviders/KeyframeInterpolator.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/Protocols/NodeOutput.hpp"
#include "Lottie/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.hpp"
namespace lottie {
class TextAnimatorNodeProperties: public KeypathSearchableNodePropertyMap {
public:
TextAnimatorNodeProperties(std::shared_ptr<TextAnimator> const &textAnimator) {
_keypathName = textAnimator->name.value_or("");
if (textAnimator->anchor) {
_anchor = std::make_shared<NodeProperty<Vector3D>>(std::make_shared<KeyframeInterpolator<Vector3D>>(textAnimator->anchor->keyframes));
_keypathProperties.insert(std::make_pair("Anchor", _anchor));
}
if (textAnimator->position) {
_position = std::make_shared<NodeProperty<Vector3D>>(std::make_shared<KeyframeInterpolator<Vector3D>>(textAnimator->position->keyframes));
_keypathProperties.insert(std::make_pair("Position", _position));
}
if (textAnimator->scale) {
_scale = std::make_shared<NodeProperty<Vector3D>>(std::make_shared<KeyframeInterpolator<Vector3D>>(textAnimator->scale->keyframes));
_keypathProperties.insert(std::make_pair("Scale", _scale));
}
if (textAnimator->skew) {
_skew = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->skew->keyframes));
_keypathProperties.insert(std::make_pair("Skew", _skew));
}
if (textAnimator->skewAxis) {
_skewAxis = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->skewAxis->keyframes));
_keypathProperties.insert(std::make_pair("Skew Axis", _skewAxis));
}
if (textAnimator->rotation) {
_rotation = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->rotation->keyframes));
_keypathProperties.insert(std::make_pair("Rotation", _rotation));
}
if (textAnimator->rotation) {
_opacity = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->opacity->keyframes));
_keypathProperties.insert(std::make_pair("Opacity", _opacity));
}
if (textAnimator->strokeColor) {
_strokeColor = std::make_shared<NodeProperty<Color>>(std::make_shared<KeyframeInterpolator<Color>>(textAnimator->strokeColor->keyframes));
_keypathProperties.insert(std::make_pair("Stroke Color", _strokeColor));
}
if (textAnimator->fillColor) {
_fillColor = std::make_shared<NodeProperty<Color>>(std::make_shared<KeyframeInterpolator<Color>>(textAnimator->fillColor->keyframes));
_keypathProperties.insert(std::make_pair("Fill Color", _fillColor));
}
if (textAnimator->strokeWidth) {
_strokeWidth = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->strokeWidth->keyframes));
_keypathProperties.insert(std::make_pair("Stroke Width", _strokeWidth));
}
if (textAnimator->tracking) {
_tracking = std::make_shared<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(textAnimator->tracking->keyframes));
_keypathProperties.insert(std::make_pair("Tracking", _tracking));
}
for (const auto &it : _keypathProperties) {
_properties.push_back(it.second);
}
}
virtual ~TextAnimatorNodeProperties() = default;
virtual std::string keypathName() const override {
return _keypathName;
}
virtual std::map<std::string, std::shared_ptr<AnyNodeProperty>> keypathProperties() const override {
return _keypathProperties;
}
virtual std::vector<std::shared_ptr<AnyNodeProperty>> &properties() override {
return _properties;
}
virtual std::vector<std::shared_ptr<KeypathSearchable>> const &childKeypaths() const override {
return _childKeypaths;
}
Transform2D caTransform() {
Vector2D anchor = Vector2D::Zero();
if (_anchor) {
auto anchor3d = _anchor->value();
anchor = Vector2D(anchor3d.x, anchor3d.y);
}
Vector2D position = Vector2D::Zero();
if (_position) {
auto position3d = _position->value();
position = Vector2D(position3d.x, position3d.y);
}
Vector2D scale = Vector2D(100.0, 100.0);
if (_scale) {
auto scale3d = _scale->value();
scale = Vector2D(scale3d.x, scale3d.y);
}
float rotation = 0.0;
if (_rotation) {
rotation = _rotation->value().value;
}
std::optional<float> skew;
if (_skew) {
skew = _skew->value().value;
}
std::optional<float> skewAxis;
if (_skewAxis) {
skewAxis = _skewAxis->value().value;
}
return Transform2D::makeTransform(
anchor,
position,
scale,
rotation,
skew,
skewAxis
);
}
virtual std::shared_ptr<CALayer> keypathLayer() const override {
return nullptr;
}
float opacity() {
if (_opacity) {
return _opacity->value().value;
} else {
return 100.0;
}
}
std::optional<Color> strokeColor() {
if (_strokeColor) {
return _strokeColor->value();
} else {
return std::nullopt;
}
}
std::optional<Color> fillColor() {
if (_fillColor) {
return _fillColor->value();
} else {
return std::nullopt;
}
}
float tracking() {
if (_tracking) {
return _tracking->value().value;
} else {
return 1.0;
}
}
float strokeWidth() {
if (_strokeWidth) {
return _strokeWidth->value().value;
} else {
return 0.0;
}
}
private:
std::string _keypathName;
std::shared_ptr<NodeProperty<Vector3D>> _anchor;
std::shared_ptr<NodeProperty<Vector3D>> _position;
std::shared_ptr<NodeProperty<Vector3D>> _scale;
std::shared_ptr<NodeProperty<Vector1D>> _skew;
std::shared_ptr<NodeProperty<Vector1D>> _skewAxis;
std::shared_ptr<NodeProperty<Vector1D>> _rotation;
std::shared_ptr<NodeProperty<Vector1D>> _opacity;
std::shared_ptr<NodeProperty<Color>> _strokeColor;
std::shared_ptr<NodeProperty<Color>> _fillColor;
std::shared_ptr<NodeProperty<Vector1D>> _strokeWidth;
std::shared_ptr<NodeProperty<Vector1D>> _tracking;
std::map<std::string, std::shared_ptr<AnyNodeProperty>> _keypathProperties;
std::vector<std::shared_ptr<KeypathSearchable>> _childKeypaths;
std::vector<std::shared_ptr<AnyNodeProperty>> _properties;
};
class TextOutputNode: virtual public NodeOutput {
public:
TextOutputNode(std::shared_ptr<TextOutputNode> parent) :
_parentTextNode(parent) {
}
virtual ~TextOutputNode() = default;
virtual std::shared_ptr<NodeOutput> parent() override {
return _parentTextNode;
}
Transform2D xform() {
if (_xform.has_value()) {
return _xform.value();
} else if (_parentTextNode) {
return _parentTextNode->xform();
} else {
return Transform2D::identity();
}
}
void setXform(Transform2D const &xform) {
_xform = xform;
}
float opacity() {
if (_opacity.has_value()) {
return _opacity.value();
} else if (_parentTextNode) {
return _parentTextNode->opacity();
} else {
return 1.0;
}
}
void setOpacity(float opacity) {
_opacity = opacity;
}
std::optional<Color> strokeColor() {
if (_strokeColor.has_value()) {
return _strokeColor.value();
} else if (_parentTextNode) {
return _parentTextNode->strokeColor();
} else {
return std::nullopt;
}
}
void setStrokeColor(std::optional<Color> strokeColor) {
_strokeColor = strokeColor;
}
std::optional<Color> fillColor() {
if (_fillColor.has_value()) {
return _fillColor.value();
} else if (_parentTextNode) {
return _parentTextNode->fillColor();
} else {
return std::nullopt;
}
}
void setFillColor(std::optional<Color> fillColor) {
_fillColor = fillColor;
}
float tracking() {
if (_tracking.has_value()) {
return _tracking.value();
} else if (_parentTextNode) {
return _parentTextNode->tracking();
} else {
return 0.0;
}
}
void setTracking(float tracking) {
_tracking = tracking;
}
float strokeWidth() {
if (_strokeWidth.has_value()) {
return _strokeWidth.value();
} else if (_parentTextNode) {
return _parentTextNode->strokeWidth();
} else {
return 0.0;
}
}
void setStrokeWidth(float strokeWidth) {
_strokeWidth = strokeWidth;
}
virtual bool hasOutputUpdates(float frame) override {
// TODO Fix This
return true;
}
virtual bool isEnabled() const override {
return _isEnabled;
}
virtual void setIsEnabled(bool isEnabled) override {
_isEnabled = isEnabled;
}
private:
std::shared_ptr<TextOutputNode> _parentTextNode;
bool _isEnabled = true;
std::optional<Transform2D> _xform;
std::optional<float> _opacity;
std::optional<Color> _strokeColor;
std::optional<Color> _fillColor;
std::optional<float> _tracking;
std::optional<float> _strokeWidth;
};
class TextAnimatorNode: public AnimatorNode {
public:
TextAnimatorNode(std::shared_ptr<TextAnimatorNode> const &parentNode, std::shared_ptr<TextAnimator> const &textAnimator) :
AnimatorNode(parentNode) {
std::shared_ptr<TextOutputNode> parentOutputNode;
if (parentNode) {
parentOutputNode = parentNode->_textOutputNode;
}
_textOutputNode = std::make_shared<TextOutputNode>(parentOutputNode);
_textAnimatorProperties = std::make_shared<TextAnimatorNodeProperties>(textAnimator);
}
virtual ~TextAnimatorNode() = default;
virtual std::shared_ptr<NodeOutput> outputNode() override {
return _textOutputNode;
}
virtual std::shared_ptr<KeypathSearchableNodePropertyMap> propertyMap() const override {
return _textAnimatorProperties;
}
virtual bool localUpdatesPermeateDownstream() override {
return true;
}
virtual void rebuildOutputs(float frame) override {
_textOutputNode->setXform(_textAnimatorProperties->caTransform());
_textOutputNode->setOpacity(((float)_textAnimatorProperties->opacity()) * 0.01f);
_textOutputNode->setStrokeColor(_textAnimatorProperties->strokeColor());
_textOutputNode->setFillColor(_textAnimatorProperties->fillColor());
_textOutputNode->setTracking(_textAnimatorProperties->tracking());
_textOutputNode->setStrokeWidth(_textAnimatorProperties->strokeWidth());
}
private:
std::shared_ptr<TextOutputNode> _textOutputNode;
std::shared_ptr<TextAnimatorNodeProperties> _textAnimatorProperties;
};
}
#endif /* TextAnimatorNode_hpp */