diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4e31fc60ba..fdb1114d35 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -185,8 +185,8 @@ endif ()
if (PAG_USE_QT)
# need to set the CMAKE_PREFIX_PATH to local QT installation path, for example :
- # set(CMAKE_PREFIX_PATH /Users/username/Qt5.13.0/5.13.0/clang_64/lib/cmake)
- find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
+ # set(CMAKE_PREFIX_PATH /Users/username/Qt6.2.0/Qt6.2.0/clang_64/lib/cmake)
+ find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets OpenGL Quick)
list(APPEND PAG_SHARED_LIBS Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGL
Qt${QT_VERSION_MAJOR}::Quick)
diff --git a/ohos/libpag/README.md b/ohos/libpag/README.md
index fb0b80232f..176020cfa7 100644
--- a/ohos/libpag/README.md
+++ b/ohos/libpag/README.md
@@ -104,7 +104,7 @@ versions, you can download the precompiled libraries from [here](https://github.
- NodeJS 14.14.0+
- Ninja 1.9.0+
- CMake 3.13.0+
-- QT 5.13.0+
+- QT 6.2.0+
- Emscripten 3.1.58+
### Dependency Management
diff --git a/viewer/qml/Main.qml b/viewer/qml/Main.qml
index 8771eebafb..952ff7c7d4 100644
--- a/viewer/qml/Main.qml
+++ b/viewer/qml/Main.qml
@@ -28,6 +28,8 @@ PAGWindow {
property int windowTitleBarHeight: isWindows ? 32 : 22
+ property int minWindowHeightWithEditPanel: 650
+
Settings {
id: settings
property bool isEditPanelOpen: false
@@ -67,6 +69,9 @@ PAGWindow {
let preferredSize = pagView.preferredSize;
let width = Math.max(viewWindow.minimumWidth, preferredSize.width);
let height = Math.max(viewWindow.minimumHeight, preferredSize.height);
+ if (settings.isEditPanelOpen) {
+ width += mainForm.rightItem.width + mainForm.splitHandleWidth;
+ }
let x = Math.max(0, oldX - ((width - oldWidth) / 2));
let y = Math.max(50, oldY - ((height - oldHeight) / 2));
settings.lastX = x;
@@ -289,9 +294,7 @@ PAGWindow {
}
function updateProgress() {
- let duration = mainForm.pagView.duration;
- let displayedTime = duration * mainForm.pagView.progress;
- mainForm.controlForm.timeDisplayedText.text = Utils.msToTime(displayedTime);
+ mainForm.controlForm.timeDisplayedText.text = mainForm.pagView.displayedTime;
mainForm.controlForm.currentFrameText.text = mainForm.pagView.currentFrame;
mainForm.controlForm.totalFrameText.text = mainForm.pagView.totalFrame;
}
@@ -312,7 +315,31 @@ PAGWindow {
if (mainForm.controlForm.panelsButton.checked !== willOpen) {
mainForm.controlForm.panelsButton.checked = willOpen;
}
+
+ if (willOpen) {
+ let widthChange = (mainForm.rightItem.width === 0) ? mainForm.minPanelWidth : mainForm.rightItem.width;
+ widthChange += mainForm.splitHandleWidth;
+ if (viewWindow.visibility === Window.FullScreen) {
+ mainForm.centerItem.width = viewWindow.width - widthChange;
+ } else {
+ viewWindow.width = viewWindow.width + widthChange;
+ }
+ mainForm.rightItem.width = widthChange;
+ if (viewWindow.height < minWindowHeightWithEditPanel) {
+ viewWindow.height = minWindowHeightWithEditPanel;
+ }
+ } else {
+ let widthChange = -1 * mainForm.rightItem.width;
+ if ((viewWindow.width + widthChange) < viewWindow.minimumWidth) {
+ viewWindow.width = viewWindow.minimumWidth;
+ } else {
+ viewWindow.width = viewWindow.width + widthChange;
+ }
+ mainForm.rightItem.width = 0;
+ }
+
settings.isEditPanelOpen = willOpen;
+ mainForm.isEditPanelOpen = willOpen;
}
function onCommand(command) {
@@ -325,14 +352,17 @@ PAGWindow {
} else {
openFileDialog.currentFolder = StandardPaths.writableLocation(StandardPaths.DocumentsLocation);
}
- openFileDialog.accepted.disconnect();
+ if (openFileDialog.currentAcceptHandler) {
+ openFileDialog.accepted.disconnect(openFileDialog.currentAcceptHandler);
+ }
openFileDialog.fileMode = FileDialog.OpenFile;
openFileDialog.title = qsTr("Open PAG File");
openFileDialog.nameFilters = ["PAG files(*.pag)"];
- openFileDialog.accepted.connect(function () {
+ openFileDialog.currentAcceptHandler = function () {
let filePath = openFileDialog.selectedFile;
mainForm.pagView.setFile(filePath);
- });
+ };
+ openFileDialog.accepted.connect(openFileDialog.currentAcceptHandler);
openFileDialog.open();
break;
case "close-window":
diff --git a/viewer/qml/MainForm.qml b/viewer/qml/MainForm.qml
index 1049b98031..75665aeff0 100644
--- a/viewer/qml/MainForm.qml
+++ b/viewer/qml/MainForm.qml
@@ -14,6 +14,8 @@ SplitView {
property int minPlayerWidth: 360
+ property int minPanelWidth: 300
+
property int splitHandleWidth: 0
property int splitHandleHeight: 0
@@ -26,6 +28,8 @@ SplitView {
property alias centerItem: centerItem
+ property alias rightItem: rightItem
+
property alias controlForm: controlForm
anchors.fill: parent
orientation: Qt.Horizontal
@@ -112,4 +116,39 @@ SplitView {
}
}
}
+
+ PAGRectangle {
+ id: rightItem
+ visible: isEditPanelOpen
+ SplitView.minimumWidth: minPanelWidth
+ SplitView.preferredWidth: minPanelWidth
+ color: "#16161d"
+ radius: 5
+ leftTopRadius: false
+ rightTopRadius: false
+ rightBottomRadius: false
+
+ PAGRectangle {
+ id: performance
+ color: "#16161D"
+ clip: true
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ anchors.right: parent.right
+ anchors.rightMargin: 0
+ anchors.left: parent.left
+ anchors.leftMargin: 0
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 0
+ radius: 5
+ leftTopRadius: false
+ rightTopRadius: false
+ leftBottomRadius: false
+
+ Profiler {
+ id: profilerForm
+ anchors.fill: parent
+ }
+ }
+ }
}
diff --git a/viewer/qml/Profiler.qml b/viewer/qml/Profiler.qml
new file mode 100644
index 0000000000..975c2c0f4e
--- /dev/null
+++ b/viewer/qml/Profiler.qml
@@ -0,0 +1,297 @@
+import PAG
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+Item {
+ id: element
+
+ property int defaultWidth: 300
+ property int defaultHeight: 300
+
+ property alias graph: graph
+ property alias graphCanvas: graphCanvas
+
+ width: defaultWidth
+ height: defaultHeight
+
+ PAGRunTimeModelManager {
+ id: runTimeModelManager
+ objectName: "runTimeModelManager"
+ }
+
+ Column {
+ spacing: 0
+ anchors {
+ fill: parent
+ leftMargin: 12
+ rightMargin: 12
+ }
+
+ Item {
+ width: parent.width
+ height: 12
+ }
+
+ /* Title */
+ Rectangle {
+ id: profilerTitle
+ color: "#2D2D37"
+ height: 25
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+
+ Item {
+ width: 10
+ height: 1
+ }
+
+ Label {
+ id: titleLabel
+ Layout.alignment: Qt.AlignVCenter
+ text: qsTr("File Info")
+ color: "#FFFFFF"
+ font.pixelSize: 10
+ visible: true
+ }
+
+ Item {
+ Layout.fillWidth: true
+ height: 1
+ }
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 1
+ }
+
+ /* File Info */
+ GridView {
+ id: fileInfoView
+ height: 93
+ width: parent.width
+ cellWidth: width / 4
+ cellHeight: 46
+ boundsBehavior: Flickable.StopAtBounds
+ keyNavigationWraps: false
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ model: runTimeModelManager.fileInfoModel
+
+ delegate: Item {
+ width: fileInfoView.cellWidth
+ height: fileInfoView.cellHeight
+
+ Rectangle {
+ height: fileInfoView.cellHeight - 1
+ width: fileInfoView.cellWidth - ((index + 1) % 4 === 0 ? 0 : 1)
+ color: "#2D2D37"
+ anchors {
+ left: parent.left
+ top: parent.top
+ rightMargin: 1
+ bottomMargin: 1
+ }
+ Text {
+ id: nameText
+ color: "#9b9b9b"
+ text: name
+ font.pixelSize: 9
+ renderType: Text.NativeRendering
+ anchors.top: parent.top
+ anchors.topMargin: 4
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ }
+
+ Text {
+ id: valueText
+ color: "#ffffff"
+ text: value
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 14
+ renderType: Text.NativeRendering
+ anchors.top: nameText.bottom
+ anchors.topMargin: 2
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 2
+ anchors.left: nameText.left
+ anchors.leftMargin: 0
+ }
+
+ Text {
+ id: extText
+ color: "#9b9b9b"
+ text: unit
+ font.pixelSize: 9
+ renderType: Text.NativeRendering
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 5
+ anchors.left: valueText.right
+ anchors.leftMargin: 3
+ }
+ }
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 2
+ }
+
+ /* performance chart */
+ Rectangle {
+ id: performanceChart
+ height: 90
+ color: "#00000000"
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ Rectangle {
+ id: graph
+ height: 90
+ color: "#2D2D37"
+ clip: true
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ Canvas {
+ id: graphCanvas
+
+ height: 70
+ width: graph.width
+ anchors.bottom: parent.bottom
+ renderStrategy: Canvas.Cooperative
+
+ onPaint: {}
+ }
+ Text {
+ id: currentFrameText
+ text: "0/0"
+ font.pixelSize: 9
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ color: "#9B9B9B"
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 4
+ }
+
+ /* Data Statistics */
+ Rectangle {
+ id: statistics
+ height: 62
+ color: "#00000000"
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ ListView {
+ id: dataListView
+
+ width: parent.width
+ boundsBehavior: ListView.StopAtBounds
+ interactive: false
+ anchors.fill: parent
+ spacing: 1
+
+ model: runTimeModelManager.frameDisplayInfoModel
+
+ delegate: Item {
+ height: 20
+ Row {
+ spacing: 1
+ Rectangle {
+ height: 20
+ width: (dataListView.width - 2) / 3
+ color: "#2D2D37"
+ Text {
+ text: name
+ font.pixelSize: 10
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ color: colorCode
+ renderType: Text.NativeRendering
+ }
+ Text {
+ text: current
+ font.pixelSize: 12
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 8
+ color: "white"
+ renderType: Text.NativeRendering
+ }
+ }
+ Rectangle {
+ height: 20
+ width: (dataListView.width - 2) / 3
+ color: "#2D2D37"
+ Text {
+ text: "AVG"
+ font.pixelSize: 10
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ color: colorCode
+ renderType: Text.NativeRendering
+ }
+ Text {
+ text: avg
+ font.pixelSize: 12
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 8
+ color: "white"
+ renderType: Text.NativeRendering
+ }
+ }
+ Rectangle {
+ height: 20
+ width: (dataListView.width - 2) / 3
+ color: "#2D2D37"
+ Text {
+ text: "MAX"
+ font.pixelSize: 10
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ color: colorCode
+ renderType: Text.NativeRendering
+ }
+ Text {
+ text: max
+ font.pixelSize: 12
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 8
+ color: "white"
+ renderType: Text.NativeRendering
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Item {
+ width: parent.width
+ height: 20
+ }
+ }
+}
diff --git a/viewer/res.qrc b/viewer/res.qrc
index bb07745699..c8ae0ed018 100644
--- a/viewer/res.qrc
+++ b/viewer/res.qrc
@@ -24,6 +24,7 @@
qml/Main.qml
qml/Menu.qml
qml/MainForm.qml
+ qml/Profiler.qml
qml/AboutWindow.qml
qml/ControlForm.qml
qml/SettingsWindow.qml
diff --git a/viewer/src/main.cpp b/viewer/src/main.cpp
index 137aa2612c..ac19e799a2 100644
--- a/viewer/src/main.cpp
+++ b/viewer/src/main.cpp
@@ -21,6 +21,7 @@
#include
#include
#include "PAGViewer.h"
+#include "profiling/PAGRunTimeModelManager.h"
#include "rendering/PAGView.h"
#include "task/PAGTaskFactory.h"
@@ -62,6 +63,7 @@ int main(int argc, char* argv[]) {
QApplication::setWindowIcon(QIcon(":/images/window-icon.png"));
qmlRegisterType("PAG", 1, 0, "PAGView");
qmlRegisterType("PAG", 1, 0, "PAGTaskFactory");
+ qmlRegisterType("PAG", 1, 0, "PAGRunTimeModelManager");
app.openFile(filePath.data());
return QApplication::exec();
diff --git a/viewer/src/profiling/PAGFileInfoModel.cpp b/viewer/src/profiling/PAGFileInfoModel.cpp
new file mode 100644
index 0000000000..60b4524c9b
--- /dev/null
+++ b/viewer/src/profiling/PAGFileInfoModel.cpp
@@ -0,0 +1,97 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "PAGFileInfoModel.h"
+#include "pag/file.h"
+#include "pag/pag.h"
+#include "utils/StringUtils.h"
+
+namespace pag {
+
+PAGFileInfo::PAGFileInfo(const QString& name, const QString& value, const QString& unit)
+ : name(name), value(value), unit(unit) {
+}
+
+PAGFileInfoModel::PAGFileInfoModel() : QAbstractListModel(nullptr) {
+}
+
+PAGFileInfoModel::PAGFileInfoModel(QObject* parent) : QAbstractListModel(parent) {
+ beginResetModel();
+ fileInfos.emplace_back("Duration", "", "s");
+ fileInfos.emplace_back("FrameRate", "", "FPS");
+ fileInfos.emplace_back("Width");
+ fileInfos.emplace_back("Height");
+ fileInfos.emplace_back("Graphics");
+ fileInfos.emplace_back("Videos");
+ fileInfos.emplace_back("Layers");
+ fileInfos.emplace_back("SDK Version");
+ endResetModel();
+}
+
+auto PAGFileInfoModel::data(const QModelIndex& index, int role) const -> QVariant {
+ if ((index.row() < 0) || (index.row() >= static_cast(fileInfos.size()))) {
+ return {};
+ }
+
+ const PAGFileInfo& fileInfo = fileInfos[index.row()];
+ auto fileInfoRole = static_cast(role);
+ if (fileInfoRole == PAGFileInfoRoles::NameRole) {
+ return fileInfo.name;
+ }
+ if (fileInfoRole == PAGFileInfoRoles::ValueRole) {
+ return fileInfo.value;
+ }
+ if (fileInfoRole == PAGFileInfoRoles::UnitRole) {
+ return fileInfo.unit;
+ }
+
+ return {};
+}
+
+auto PAGFileInfoModel::rowCount(const QModelIndex& parent) const -> int {
+ Q_UNUSED(parent);
+ return static_cast(fileInfos.size());
+}
+
+auto PAGFileInfoModel::resetFile(const std::shared_ptr& pagFile,
+ const std::string& filePath) -> void {
+ Q_UNUSED(filePath);
+ beginResetModel();
+ fileInfos.clear();
+ fileInfos.emplace_back("Duration", Utils::toQString(pagFile->duration() / 1000000.0), "s");
+ fileInfos.emplace_back("FrameRate", Utils::toQString(pagFile->frameRate()), "FPS");
+ fileInfos.emplace_back("Width", Utils::toQString(pagFile->width()));
+ fileInfos.emplace_back("Height", Utils::toQString(pagFile->height()));
+ auto memorySize = CalculateGraphicsMemory(pagFile->getFile());
+ fileInfos.emplace_back("Graphics", Utils::getMemorySizeNumString(memorySize),
+ Utils::getMemorySizeUnit(memorySize));
+ fileInfos.emplace_back("Videos", Utils::toQString(pagFile->numVideos()));
+ fileInfos.emplace_back("Layers", Utils::toQString(pagFile->getFile()->numLayers()));
+ auto version = Utils::tagCodeToVersion(pagFile->tagLevel());
+ fileInfos.emplace_back("SDK Version", version.c_str());
+ endResetModel();
+}
+
+auto PAGFileInfoModel::roleNames() const -> QHash {
+ static QHash roles = {{static_cast(PAGFileInfoRoles::NameRole), "name"},
+ {static_cast(PAGFileInfoRoles::ValueRole), "value"},
+ {static_cast(PAGFileInfoRoles::UnitRole), "unit"}};
+ return roles;
+}
+
+} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/profiling/PAGFileInfoModel.h b/viewer/src/profiling/PAGFileInfoModel.h
new file mode 100644
index 0000000000..f2a1cdeb3d
--- /dev/null
+++ b/viewer/src/profiling/PAGFileInfoModel.h
@@ -0,0 +1,53 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include
+#include "pag/pag.h"
+
+namespace pag {
+class PAGFileInfo {
+ public:
+ explicit PAGFileInfo(const QString& name, const QString& value = "", const QString& unit = "");
+
+ QString name = "";
+ QString value = "";
+ QString unit = "";
+};
+
+class PAGFileInfoModel : public QAbstractListModel {
+ Q_OBJECT
+ public:
+ enum class PAGFileInfoRoles { NameRole = Qt::UserRole + 1, ValueRole, UnitRole };
+
+ PAGFileInfoModel();
+ explicit PAGFileInfoModel(QObject* parent);
+
+ auto data(const QModelIndex& index, int role) const -> QVariant override;
+ auto rowCount(const QModelIndex& parent) const -> int override;
+ auto resetFile(const std::shared_ptr& pagFile, const std::string& filePath) -> void;
+
+ protected:
+ auto roleNames() const -> QHash override;
+
+ private:
+ std::vector fileInfos = {};
+};
+
+} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/profiling/PAGFrameDisplayInfoModel.cpp b/viewer/src/profiling/PAGFrameDisplayInfoModel.cpp
new file mode 100644
index 0000000000..2e6bce7cfe
--- /dev/null
+++ b/viewer/src/profiling/PAGFrameDisplayInfoModel.cpp
@@ -0,0 +1,88 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "PAGFrameDisplayInfoModel.h"
+
+namespace pag {
+
+FrameDisplayInfo::FrameDisplayInfo(const QString& name, const QString& color, int64_t current,
+ int64_t avg, int64_t max)
+ : name(name), color(color), current(current), avg(avg), max(max) {
+}
+
+PAGFrameDisplayInfoModel::PAGFrameDisplayInfoModel() : QAbstractListModel(nullptr) {
+}
+
+PAGFrameDisplayInfoModel::PAGFrameDisplayInfoModel(QObject* parent) : QAbstractListModel(parent) {
+}
+
+auto PAGFrameDisplayInfoModel::data(const QModelIndex& index, int role) const -> QVariant {
+ if ((index.row() < 0) || (index.row() >= static_cast(diplayInfos.size()))) {
+ return {};
+ }
+
+ const auto& item = diplayInfos[index.row()];
+ switch (static_cast(role)) {
+ case PAGFrameDisplayInfoRoles::NameRole: {
+ return item.name;
+ }
+ case PAGFrameDisplayInfoRoles::ColorRole: {
+ return item.color;
+ }
+ case PAGFrameDisplayInfoRoles::CurrentRole: {
+ return QString::number(item.current);
+ }
+ case PAGFrameDisplayInfoRoles::AvgRole: {
+ return QString::number(item.avg);
+ }
+ case PAGFrameDisplayInfoRoles::MaxRole: {
+ return QString::number(item.max);
+ }
+ default:
+ return {};
+ }
+}
+
+auto PAGFrameDisplayInfoModel::rowCount(const QModelIndex& parent) const -> int {
+ Q_UNUSED(parent);
+ return static_cast(diplayInfos.size());
+}
+
+auto PAGFrameDisplayInfoModel::updateData(const FrameDisplayInfo& render,
+ const FrameDisplayInfo& present,
+ const FrameDisplayInfo& imageDecode) -> void {
+
+ beginResetModel();
+ diplayInfos.clear();
+ diplayInfos.push_back(render);
+ diplayInfos.push_back(imageDecode);
+ diplayInfos.push_back(present);
+ endResetModel();
+}
+
+auto PAGFrameDisplayInfoModel::roleNames() const -> QHash {
+ static const QHash roles = {
+ {static_cast(PAGFrameDisplayInfoRoles::NameRole), "name"},
+ {static_cast(PAGFrameDisplayInfoRoles::ColorRole), "colorCode"},
+ {static_cast(PAGFrameDisplayInfoRoles::CurrentRole), "current"},
+ {static_cast(PAGFrameDisplayInfoRoles::AvgRole), "avg"},
+ {static_cast(PAGFrameDisplayInfoRoles::MaxRole), "max"}};
+ return roles;
+}
+
+} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/profiling/PAGFrameDisplayInfoModel.h b/viewer/src/profiling/PAGFrameDisplayInfoModel.h
new file mode 100644
index 0000000000..d33969bd8a
--- /dev/null
+++ b/viewer/src/profiling/PAGFrameDisplayInfoModel.h
@@ -0,0 +1,64 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include
+#include
+
+namespace pag {
+
+class FrameDisplayInfo {
+ public:
+ FrameDisplayInfo(const QString& name, const QString& color, int64_t current, int64_t avg,
+ int64_t max);
+
+ QString name = "";
+ QString color = "";
+ int64_t current = 0;
+ int64_t avg = 0;
+ int64_t max = 0;
+};
+
+class PAGFrameDisplayInfoModel : public QAbstractListModel {
+ Q_OBJECT
+ public:
+ enum class PAGFrameDisplayInfoRoles {
+ NameRole = Qt::UserRole + 1,
+ ColorRole,
+ CurrentRole,
+ AvgRole,
+ MaxRole
+ };
+
+ PAGFrameDisplayInfoModel();
+ explicit PAGFrameDisplayInfoModel(QObject* parent);
+
+ auto data(const QModelIndex& index, int role) const -> QVariant override;
+ auto rowCount(const QModelIndex& parent) const -> int override;
+ auto updateData(const FrameDisplayInfo& render, const FrameDisplayInfo& present,
+ const FrameDisplayInfo& imageDecode) -> void;
+
+ protected:
+ auto roleNames() const -> QHash override;
+
+ private:
+ std::vector diplayInfos = {};
+};
+
+} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/profiling/PAGRunTimeModelManager.cpp b/viewer/src/profiling/PAGRunTimeModelManager.cpp
new file mode 100644
index 0000000000..d984700e14
--- /dev/null
+++ b/viewer/src/profiling/PAGRunTimeModelManager.cpp
@@ -0,0 +1,118 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "PAGRunTimeModelManager.h"
+#include "base/utils/TimeUtil.h"
+#include "pag/pag.h"
+
+namespace pag {
+
+FrameTimeMetrics::FrameTimeMetrics(int64_t renderTime, int64_t presentTime, int64_t imageDecodeTime)
+ : renderTime(renderTime), presentTime(presentTime), imageDecodeTime(imageDecodeTime) {
+}
+
+PAGRunTimeModelManager::PAGRunTimeModelManager(QObject* parent) : QObject(parent) {
+}
+
+auto PAGRunTimeModelManager::getTotalFrame() const -> QString {
+ return QString::number(totalFrame);
+}
+
+auto PAGRunTimeModelManager::getCurrentFrame() const -> QString {
+ return QString::number(currentFrame);
+}
+
+auto PAGRunTimeModelManager::getFileInfoModel() const -> const PAGFileInfoModel* {
+ return &fileInfoModel;
+}
+
+auto PAGRunTimeModelManager::getFrameDisplayInfoModel() const -> const PAGFrameDisplayInfoModel* {
+ return &frameDisplayInfoModel;
+}
+
+auto PAGRunTimeModelManager::setCurrentFrame(const QString& currentFrame) -> void {
+ if (this->currentFrame == currentFrame.toLongLong()) {
+ return;
+ }
+ this->currentFrame = currentFrame.toLongLong();
+ Q_EMIT dataChanged();
+}
+
+auto PAGRunTimeModelManager::updateData(int64_t currentFrame, int64_t renderTime,
+ int64_t presentTime, int64_t imageDecodeTime) -> void {
+ if (this->currentFrame == currentFrame) {
+ return;
+ }
+ this->currentFrame = currentFrame;
+ if (currentFrame >= frameTimeMetricsVector.size()) {
+ frameTimeMetricsVector.push_back(FrameTimeMetrics(renderTime, presentTime, imageDecodeTime));
+ } else {
+ frameTimeMetricsVector[currentFrame] =
+ FrameTimeMetrics(renderTime, presentTime, imageDecodeTime);
+ }
+ updateFrameDisplayInfo(renderTime, presentTime, imageDecodeTime);
+ Q_EMIT dataChanged();
+}
+
+auto PAGRunTimeModelManager::resetFile(const std::shared_ptr& pagFile,
+ const std::string& filePath) -> void {
+ totalFrame = TimeToFrame(pagFile->duration(), pagFile->frameRate());
+ currentFrame = -1;
+ frameTimeMetricsVector.resize(totalFrame, {0, 0, 0});
+ frameTimeMetricsVector.squeeze();
+ frameTimeMetricsVector.clear();
+ fileInfoModel.resetFile(pagFile, filePath);
+ updateFrameDisplayInfo(0, 0, 0);
+ Q_EMIT dataChanged();
+}
+
+auto PAGRunTimeModelManager::updateFrameDisplayInfo(int64_t renderTime, int64_t presentTime,
+ int64_t imageDecodeTime) -> void {
+ int64_t renderAvg = 0;
+ int64_t renderMax = 0;
+ int64_t renderTotal = 0;
+ int64_t presentAvg = 0;
+ int64_t presentMax = 0;
+ int64_t presentTotal = 0;
+ int64_t imageDecodeAvg = 0;
+ int64_t imageDecodeMax = 0;
+ int64_t imageDecodeTotal = 0;
+ int64_t size = static_cast(frameTimeMetricsVector.size());
+
+ if (size > 0) {
+ for (auto& item : frameTimeMetricsVector) {
+ renderTotal += item.renderTime;
+ renderMax = std::max(item.renderTime, renderMax);
+ presentTotal += item.presentTime;
+ presentMax = std::max(item.presentTime, presentMax);
+ imageDecodeTotal += item.imageDecodeTime;
+ imageDecodeMax = std::max(item.imageDecodeTime, imageDecodeMax);
+ }
+ renderAvg = renderTotal / size;
+ presentAvg = presentTotal / size;
+ imageDecodeAvg = imageDecodeTotal / size;
+ }
+
+ FrameDisplayInfo renderInfo("Render", "#0096D8", renderTime, renderAvg, renderMax);
+ FrameDisplayInfo presentInfo("Present", "#DDB259", presentTime, presentAvg, presentMax);
+ FrameDisplayInfo imageDecodeInfo("Image", "#74AD59", imageDecodeTime, imageDecodeAvg,
+ imageDecodeMax);
+ frameDisplayInfoModel.updateData(renderInfo, presentInfo, imageDecodeInfo);
+}
+
+} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/profiling/PAGRunTimeModelManager.h b/viewer/src/profiling/PAGRunTimeModelManager.h
new file mode 100644
index 0000000000..23d9883235
--- /dev/null
+++ b/viewer/src/profiling/PAGRunTimeModelManager.h
@@ -0,0 +1,78 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include
+#include "profiling/PAGFileInfoModel.h"
+#include "profiling/PAGFrameDisplayInfoModel.h"
+
+namespace pag {
+
+class FrameTimeMetrics {
+ public:
+ FrameTimeMetrics(int64_t renderTime, int64_t presentTime, int64_t imageDecodeTime);
+
+ int64_t renderTime = 0;
+ int64_t presentTime = 0;
+ int64_t imageDecodeTime = 0;
+};
+
+class PAGRunTimeModelManager : public QObject {
+ Q_OBJECT
+ public:
+ explicit PAGRunTimeModelManager(QObject* parent = nullptr);
+
+ Q_PROPERTY(QString totalFrame READ getTotalFrame NOTIFY totalFrameChanged)
+ Q_PROPERTY(
+ QString currentFrame READ getCurrentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged)
+ Q_PROPERTY(
+ const PAGFileInfoModel* fileInfoModel READ getFileInfoModel NOTIFY fileInfoModelChanged)
+ Q_PROPERTY(const PAGFrameDisplayInfoModel* frameDisplayInfoModel READ getFrameDisplayInfoModel
+ NOTIFY frameDisplayInfoModelChanged)
+
+ auto getTotalFrame() const -> QString;
+ auto getCurrentFrame() const -> QString;
+ auto getFileInfoModel() const -> const PAGFileInfoModel*;
+ auto getFrameDisplayInfoModel() const -> const PAGFrameDisplayInfoModel*;
+
+ auto setCurrentFrame(const QString& currentFrame) -> void;
+
+ Q_SIGNAL void totalFrameChanged();
+ Q_SIGNAL void currentFrameChanged();
+ Q_SIGNAL void fileInfoModelChanged();
+ Q_SIGNAL void frameDisplayInfoModelChanged();
+ Q_SIGNAL void dataChanged();
+
+ Q_SLOT void updateData(int64_t currentFrame, int64_t renderTime, int64_t presentTime,
+ int64_t imageDecodeTime);
+
+ auto resetFile(const std::shared_ptr& pagFile, const std::string& filePath) -> void;
+
+ private:
+ auto updateFrameDisplayInfo(int64_t renderTime, int64_t presentTime, int64_t imageDecodeTime)
+ -> void;
+
+ private:
+ int64_t totalFrame = -1;
+ int64_t currentFrame = -1;
+ PAGFileInfoModel fileInfoModel = {};
+ PAGFrameDisplayInfoModel frameDisplayInfoModel = {};
+ QVector frameTimeMetricsVector = {};
+};
+} // namespace pag
diff --git a/viewer/src/rendering/PAGRenderThread.cpp b/viewer/src/rendering/PAGRenderThread.cpp
index 15356ea586..a50bedb9ff 100644
--- a/viewer/src/rendering/PAGRenderThread.cpp
+++ b/viewer/src/rendering/PAGRenderThread.cpp
@@ -26,7 +26,17 @@ PAGRenderThread::PAGRenderThread(PAGView* pagView) : pagView(pagView) {
}
auto PAGRenderThread::flush() -> void {
+ if (pagView->pagPlayer == nullptr || pagView->pagFile == nullptr) {
+ return;
+ }
pagView->pagPlayer->flush();
+ double progress = pagView->pagFile->getProgress();
+ int64_t currentFrame =
+ static_cast(std::round((pagView->getTotalFrame().toDouble() - 1) * progress));
+ int64_t renderingTime = pagView->pagPlayer->renderingTime();
+ int64_t presentingTime = pagView->pagPlayer->presentingTime();
+ int64_t imageDecodingTime = pagView->pagPlayer->imageDecodingTime();
+ Q_EMIT frameTimeMetricsReady(currentFrame, renderingTime, presentingTime, imageDecodingTime);
QMetaObject::invokeMethod(pagView, "update", Qt::QueuedConnection);
}
diff --git a/viewer/src/rendering/PAGRenderThread.h b/viewer/src/rendering/PAGRenderThread.h
index f0cf51e2b1..50b24e1bdc 100644
--- a/viewer/src/rendering/PAGRenderThread.h
+++ b/viewer/src/rendering/PAGRenderThread.h
@@ -29,6 +29,9 @@ class PAGRenderThread : public QThread {
public:
explicit PAGRenderThread(PAGView* pagView);
+ Q_SIGNAL void frameTimeMetricsReady(int64_t frame, int64_t renderTime, int64_t presentTime,
+ int64_t imageDecodeTime);
+
Q_SLOT void flush();
Q_SLOT void shutDown();
diff --git a/viewer/src/rendering/PAGView.cpp b/viewer/src/rendering/PAGView.cpp
index 969adeadaa..eb33279313 100644
--- a/viewer/src/rendering/PAGView.cpp
+++ b/viewer/src/rendering/PAGView.cpp
@@ -34,6 +34,12 @@ PAGView::PAGView(QQuickItem* parent) : QQuickItem(parent) {
drawable->moveToThread(renderThread.get());
}
+auto PAGView::flush() const -> void {
+ if (isPlaying_) {
+ QMetaObject::invokeMethod(renderThread.get(), "flush", Qt::QueuedConnection);
+ }
+}
+
PAGView::~PAGView() {
QMetaObject::invokeMethod(renderThread.get(), "shutDown", Qt::QueuedConnection);
renderThread->wait();
@@ -41,32 +47,34 @@ PAGView::~PAGView() {
auto PAGView::getPAGWidth() const -> int {
if (pagFile == nullptr) {
- return -1;
+ return 0;
}
return pagFile->width();
}
auto PAGView::getPAGHeight() const -> int {
if (pagFile == nullptr) {
- return -1;
+ return 0;
}
return pagFile->height();
}
-auto PAGView::getTotalFrame() const -> int {
+auto PAGView::getTotalFrame() const -> QString {
if (pagFile == nullptr) {
- return 0;
+ return "0";
}
- int totalFrames = static_cast(std::round(getDuration() * pagFile->frameRate() / 1000.0));
+ int64_t totalFrames =
+ static_cast(std::round(getDuration().toLongLong() * pagFile->frameRate() / 1000.0));
if (totalFrames < 1) {
totalFrames = 0;
}
- return totalFrames;
+ return QString::number(totalFrames);
}
-auto PAGView::getCurrentFrame() const -> int {
- int totalFrames = getTotalFrame();
- return static_cast(std::round(getProgress() * (totalFrames - 1)));
+auto PAGView::getCurrentFrame() const -> QString {
+ int64_t totalFrames = getTotalFrame().toLongLong();
+ int64_t currentFrame = static_cast(std::round(getProgress() * (totalFrames - 1)));
+ return QString::number(currentFrame);
}
auto PAGView::isPlaying() const -> bool {
@@ -80,11 +88,11 @@ auto PAGView::getShowVideoFrames() const -> bool {
return pagPlayer->videoEnabled();
}
-auto PAGView::getDuration() const -> double {
+auto PAGView::getDuration() const -> QString {
if (pagPlayer == nullptr) {
- return 0.0;
+ return "0";
}
- return static_cast(pagPlayer->duration()) / 1000.0;
+ return QString::number(pagPlayer->duration() / 1000);
}
auto PAGView::getProgress() const -> double {
@@ -95,6 +103,16 @@ auto PAGView::getFilePath() const -> QString {
return filePath;
}
+auto PAGView::getDisplayedTime() const -> QString {
+ int64_t displayedTime =
+ static_cast(std::round(getProgress() * getDuration().toLongLong() / 1000.0));
+ int64_t displayedSeconds = displayedTime % 60;
+ int64_t displayedMinutes = (displayedTime / 60) % 60;
+ return QString("%1:%2")
+ .arg(displayedMinutes, 2, 10, QChar('0'))
+ .arg(displayedSeconds, 2, 10, QChar('0'));
+}
+
auto PAGView::getBackgroundColor() const -> QColor {
if (pagFile == nullptr) {
return QColorConstants::Black;
@@ -105,10 +123,6 @@ auto PAGView::getBackgroundColor() const -> QColor {
}
auto PAGView::getPreferredSize() const -> QSizeF {
- if (pagFile == nullptr) {
- return {0, 0};
- }
-
auto quickWindow = window();
int pagWidth = getPAGWidth();
int pagHeight = getPAGHeight();
@@ -136,9 +150,6 @@ auto PAGView::getPreferredSize() const -> QSizeF {
}
auto PAGView::setIsPlaying(bool isPlaying) -> void {
- if (pagFile == nullptr) {
- return;
- }
if (this->isPlaying_ == isPlaying) {
return;
}
@@ -194,25 +205,16 @@ auto PAGView::setFile(const QString& filePath) -> bool {
}
auto PAGView::firstFrame() -> void {
- if (pagFile == nullptr) {
- return;
- }
setIsPlaying(false);
setProgress(0);
}
auto PAGView::lastFrame() -> void {
- if (pagFile == nullptr) {
- return;
- }
setIsPlaying(false);
setProgress(1);
}
auto PAGView::nextFrame() -> void {
- if (pagFile == nullptr) {
- return;
- }
setIsPlaying(false);
auto progress = this->progress + progressPerFrame;
if (progress > 1) {
@@ -222,9 +224,6 @@ auto PAGView::nextFrame() -> void {
}
auto PAGView::previousFrame() -> void {
- if (pagFile == nullptr) {
- return;
- }
setIsPlaying(false);
auto progress = this->progress - progressPerFrame;
if (progress < 0) {
@@ -274,8 +273,11 @@ QSGNode* PAGView::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) {
}
setProgress(progress);
}
- QMetaObject::invokeMethod(renderThread.get(), "flush", Qt::QueuedConnection);
}
return node;
}
+
+auto PAGView::getRenderThread() const -> PAGRenderThread* {
+ return renderThread.get();
+}
} // namespace pag
\ No newline at end of file
diff --git a/viewer/src/rendering/PAGView.h b/viewer/src/rendering/PAGView.h
index 91cc00b0b5..b39312e840 100644
--- a/viewer/src/rendering/PAGView.h
+++ b/viewer/src/rendering/PAGView.h
@@ -34,25 +34,28 @@ class PAGView : public QQuickItem {
Q_PROPERTY(int pagWidth READ getPAGWidth)
Q_PROPERTY(int pagHeight READ getPAGHeight)
- Q_PROPERTY(int totalFrame READ getTotalFrame)
- Q_PROPERTY(int currentFrame READ getCurrentFrame)
Q_PROPERTY(bool isPlaying READ isPlaying WRITE setIsPlaying NOTIFY isPlayingChanged)
Q_PROPERTY(bool showVideoFrames READ getShowVideoFrames WRITE setShowVideoFrames)
- Q_PROPERTY(double duration READ getDuration)
Q_PROPERTY(double progress READ getProgress WRITE setProgress NOTIFY progressChanged)
+ Q_PROPERTY(QString totalFrame READ getTotalFrame)
+ Q_PROPERTY(QString currentFrame READ getCurrentFrame)
+ Q_PROPERTY(QString duration READ getDuration)
Q_PROPERTY(QString filePath READ getFilePath NOTIFY fileChanged)
+ Q_PROPERTY(QString displayedTime READ getDisplayedTime)
Q_PROPERTY(QColor backgroundColor READ getBackgroundColor)
Q_PROPERTY(QSizeF preferredSize READ getPreferredSize)
auto getPAGWidth() const -> int;
auto getPAGHeight() const -> int;
- auto getTotalFrame() const -> int;
- auto getCurrentFrame() const -> int;
+
auto isPlaying() const -> bool;
auto getShowVideoFrames() const -> bool;
- auto getDuration() const -> double;
auto getProgress() const -> double;
+ auto getTotalFrame() const -> QString;
+ auto getCurrentFrame() const -> QString;
+ auto getDuration() const -> QString;
auto getFilePath() const -> QString;
+ auto getDisplayedTime() const -> QString;
auto getBackgroundColor() const -> QColor;
auto getPreferredSize() const -> QSizeF;
@@ -65,6 +68,8 @@ class PAGView : public QQuickItem {
Q_SIGNAL void fileChanged(const std::shared_ptr& pagFile,
const std::string& filePath);
+ Q_SLOT void flush() const;
+
Q_INVOKABLE bool setFile(const QString& filePath);
Q_INVOKABLE void firstFrame();
Q_INVOKABLE void lastFrame();
@@ -72,6 +77,7 @@ class PAGView : public QQuickItem {
Q_INVOKABLE void previousFrame();
auto updatePaintNode(QSGNode*, UpdatePaintNodeData*) -> QSGNode* override;
+ auto getRenderThread() const -> PAGRenderThread*;
private:
int64_t lastPlayTime = 0;
diff --git a/viewer/src/rendering/PAGWindow.cpp b/viewer/src/rendering/PAGWindow.cpp
index d62c2cbd37..89245846b2 100644
--- a/viewer/src/rendering/PAGWindow.cpp
+++ b/viewer/src/rendering/PAGWindow.cpp
@@ -18,8 +18,9 @@
#include "PAGWindow.h"
#include
-#include
+#include "PAGRenderThread.h"
#include "PAGWindowHelper.h"
+#include "profiling/PAGRunTimeModelManager.h"
#include "task/PAGTaskFactory.h"
namespace pag {
@@ -58,13 +59,22 @@ auto PAGWindow::open() -> void {
window->setPersistentGraphics(true);
window->setPersistentSceneGraph(true);
window->setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
+ auto surfaceFormat = window->format();
+ surfaceFormat.setSwapInterval(1);
+ window->setFormat(surfaceFormat);
pagView = window->findChild("pagView");
auto* taskFactory = window->findChild("taskFactory");
+ auto* runTimeModelManager = window->findChild("runTimeModelManager");
+ PAGRenderThread* renderThread = pagView->getRenderThread();
connect(window, SIGNAL(closing(QQuickCloseEvent*)), this, SLOT(onPAGViewerDestroyed()),
Qt::QueuedConnection);
+ connect(window, &QQuickWindow::afterRendering, pagView, &PAGView::flush);
connect(pagView, &PAGView::fileChanged, taskFactory, &PAGTaskFactory::resetFile);
+ connect(pagView, &PAGView::fileChanged, runTimeModelManager, &PAGRunTimeModelManager::resetFile);
+ connect(renderThread, &PAGRenderThread::frameTimeMetricsReady, runTimeModelManager,
+ &PAGRunTimeModelManager::updateData);
}
auto PAGWindow::getFilePath() -> QString {
diff --git a/viewer/src/task/PAGTask.cpp b/viewer/src/task/PAGTask.cpp
index 7b30fe2697..5d1b4aee33 100644
--- a/viewer/src/task/PAGTask.cpp
+++ b/viewer/src/task/PAGTask.cpp
@@ -18,7 +18,7 @@
#include "PAGTask.h"
#include "base/utils/TimeUtil.h"
-#include "utils/PAGFileUtils.h"
+#include "utils/FileUtils.h"
namespace pag {
diff --git a/viewer/src/task/export/PAGExportAPNGTask.cpp b/viewer/src/task/export/PAGExportAPNGTask.cpp
index 551ed6dbf2..bef55ec0f2 100644
--- a/viewer/src/task/export/PAGExportAPNGTask.cpp
+++ b/viewer/src/task/export/PAGExportAPNGTask.cpp
@@ -18,8 +18,8 @@
#include "PAGExportAPNGTask.h"
#include
-#include "utils/PAGFileUtils.h"
-#include "utils/PAGUtils.h"
+#include "utils/FileUtils.h"
+#include "utils/Utils.h"
namespace pag {
diff --git a/viewer/src/task/export/PAGExportPNGTask.cpp b/viewer/src/task/export/PAGExportPNGTask.cpp
index d5544820fb..972038580c 100644
--- a/viewer/src/task/export/PAGExportPNGTask.cpp
+++ b/viewer/src/task/export/PAGExportPNGTask.cpp
@@ -19,7 +19,7 @@
#include "task/export/PAGExportPNGTask.h"
#include
#include
-#include "utils/PAGFileUtils.h"
+#include "utils/FileUtils.h"
namespace pag {
diff --git a/viewer/src/utils/PAGFileUtils.cpp b/viewer/src/utils/FileUtils.cpp
similarity index 98%
rename from viewer/src/utils/PAGFileUtils.cpp
rename to viewer/src/utils/FileUtils.cpp
index 2ae7061d80..6ca38698fa 100644
--- a/viewer/src/utils/PAGFileUtils.cpp
+++ b/viewer/src/utils/FileUtils.cpp
@@ -16,7 +16,7 @@
//
/////////////////////////////////////////////////////////////////////////////////////////////////
-#include "utils/PAGFileUtils.h"
+#include "FileUtils.h"
#include
#include
#include
diff --git a/viewer/src/utils/PAGFileUtils.h b/viewer/src/utils/FileUtils.h
similarity index 100%
rename from viewer/src/utils/PAGFileUtils.h
rename to viewer/src/utils/FileUtils.h
diff --git a/viewer/src/utils/StringUtils.cpp b/viewer/src/utils/StringUtils.cpp
new file mode 100644
index 0000000000..6b88b37df3
--- /dev/null
+++ b/viewer/src/utils/StringUtils.cpp
@@ -0,0 +1,88 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "StringUtils.h"
+#include
+
+namespace pag::Utils {
+
+auto toQString(double num) -> QString {
+ QString result;
+ return result.setNum(num, 'f', 2);
+ ;
+}
+
+auto toQString(int32_t num) -> QString {
+ QString result;
+ return result.setNum(num);
+}
+
+auto toQString(int64_t num) -> QString {
+ QString result;
+ return result.setNum(num);
+}
+
+auto getMemorySizeUnit(int64_t size) -> QString {
+ constexpr int64_t kbThreshold = 1024;
+ constexpr int64_t mbThreshold = 1024 * 1024;
+ constexpr int64_t gbThreshold = 1024 * 1024 * 1024;
+ if (size < kbThreshold) {
+ return "B";
+ }
+ if (size < mbThreshold) {
+ return "KB";
+ }
+ if (size < gbThreshold) {
+ return "MB";
+ }
+ return "GB";
+}
+
+auto getMemorySizeNumString(int64_t size) -> QString {
+ constexpr double kbThreshold = 1024;
+ constexpr double mbThreshold = 1024 * 1024;
+ constexpr double gbThreshold = 1024 * 1024 * 1024;
+ double dSize = static_cast(size);
+ if (dSize < kbThreshold) {
+ return toQString(size);
+ }
+ if (dSize < mbThreshold) {
+ return toQString(dSize / static_cast(kbThreshold));
+ }
+ if (dSize < gbThreshold) {
+ return toQString(dSize / static_cast(mbThreshold));
+ }
+ return toQString(dSize / static_cast(gbThreshold));
+}
+
+using TagCodeVersionPair = std::pair;
+static const std::vector TagCodeVersionList = {
+ {pag::TagCode::FileAttributes, "1.0"}, {pag::TagCode::LayerAttributesExtra, "2.0"},
+ {pag::TagCode::MosaicEffect, "3.2"}, {pag::TagCode::GradientOverlayStyle, "4.1"},
+ {pag::TagCode::CameraOption, "4.2"}, {pag::TagCode::ImageScaleModes, "4.3"}};
+
+auto tagCodeToVersion(uint16_t tagCode) -> std::string {
+ for (const auto& pair : TagCodeVersionList) {
+ if (tagCode <= static_cast(pair.first)) {
+ return pair.second;
+ }
+ }
+ return "Unknown";
+}
+
+} // namespace pag::Utils
\ No newline at end of file
diff --git a/viewer/src/utils/StringUtils.h b/viewer/src/utils/StringUtils.h
new file mode 100644
index 0000000000..6c4bc3c5df
--- /dev/null
+++ b/viewer/src/utils/StringUtils.h
@@ -0,0 +1,32 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making libpag available.
+//
+// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+// except in compliance with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include
+
+namespace pag::Utils {
+
+auto toQString(double num) -> QString;
+auto toQString(int32_t num) -> QString;
+auto toQString(int64_t num) -> QString;
+auto getMemorySizeUnit(int64_t size) -> QString;
+auto getMemorySizeNumString(int64_t size) -> QString;
+auto tagCodeToVersion(uint16_t tagCode) -> std::string;
+
+} // namespace pag::Utils
\ No newline at end of file
diff --git a/viewer/src/utils/PAGUtils.cpp b/viewer/src/utils/Utils.cpp
similarity index 98%
rename from viewer/src/utils/PAGUtils.cpp
rename to viewer/src/utils/Utils.cpp
index 45d09457f0..46383a1df5 100644
--- a/viewer/src/utils/PAGUtils.cpp
+++ b/viewer/src/utils/Utils.cpp
@@ -16,7 +16,7 @@
//
/////////////////////////////////////////////////////////////////////////////////////////////////
-#include "PAGUtils.h"
+#include "Utils.h"
#include "utils/apng/APNGAssembler.h"
namespace pag::Utils {
diff --git a/viewer/src/utils/PAGUtils.h b/viewer/src/utils/Utils.h
similarity index 100%
rename from viewer/src/utils/PAGUtils.h
rename to viewer/src/utils/Utils.h