230 lines
7.7 KiB
C++
230 lines
7.7 KiB
C++
#include "RenderAble.h"
|
|
|
|
#include <QDir>
|
|
|
|
#include "base/Plot.h"
|
|
#include "Axis/AbsAxis.h"
|
|
#include "plottable/HoverInfo.h"
|
|
#include "psc_global_include/export.h"
|
|
#include "psc_global_include/Fail_Fast.h"
|
|
|
|
|
|
namespace YSG {
|
|
QDebug operator<<(QDebug debug, const Range& range) {
|
|
QDebugStateSaver saver(debug); // 保存当前的 qDebug 状态
|
|
debug.nospace() << "Range(" << range.lower << ", " << range.upper << ")";
|
|
return debug;
|
|
}
|
|
|
|
void SpinLock::lock() {
|
|
while (flag.test_and_set(std::memory_order_acquire)) {}
|
|
}
|
|
bool SpinLock::tryLock() {
|
|
return !flag.test_and_set(std::memory_order_acquire);
|
|
}
|
|
bool SpinLock::tryLock(int durationMillis) {
|
|
if (durationMillis == 0) {
|
|
return tryLock();
|
|
}
|
|
auto duration = std::chrono::milliseconds(durationMillis);
|
|
auto start = std::chrono::steady_clock::now();
|
|
while (std::chrono::steady_clock::now() - start < duration) {
|
|
if (tryLock()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
void SpinLock::unlock() {
|
|
flag.clear(std::memory_order_release);
|
|
}
|
|
SpinLockGuard::~SpinLockGuard() {
|
|
if (mLock) mLock->unlock();
|
|
}
|
|
SpinLockGuard::SpinLockGuard(SpinLock *lock) : mLock(lock) {
|
|
if (mLock) mLock->lock();
|
|
}
|
|
RenderAble::RenderPipeline::RenderPipeline() {
|
|
frontColor = &colorBuffers[0];
|
|
readyColor = &colorBuffers[1];
|
|
renderColor = &colorBuffers[2];
|
|
}
|
|
void RenderAble::RenderPipeline::markEditState() {
|
|
editStateVersion.fetch_add(1, std::memory_order_release);
|
|
}
|
|
bool RenderAble::RenderPipeline::hasNewState() const {
|
|
return RenderAble::version_newer(editStateVersion.load(std::memory_order_acquire), renderStateVersion);
|
|
}
|
|
RenderAble::ColorBuffer* RenderAble::RenderPipeline::currentRenderColor() const {
|
|
return renderColor;
|
|
}
|
|
QRegion RenderAble::RenderPipeline::publishRenderColor() {
|
|
QRegion updateRegion;
|
|
SpinLockGuard guard(&colorLock);
|
|
if(RenderAble::version_newer(renderColor->version, readyColor->version)) {
|
|
std::swap(readyColor, renderColor);
|
|
dirtyRegion += readyColor->dirtyRegion;
|
|
}
|
|
if(RenderAble::version_newer(readyColor->version, frontColor->version)) {
|
|
if(dirtyRegion.isEmpty()) dirtyRegion = readyColor->dirtyRegion;
|
|
if(!paintRequestPending) {
|
|
paintRequestPending = true;
|
|
updateRegion = dirtyRegion;
|
|
}
|
|
}
|
|
return updateRegion;
|
|
}
|
|
RenderAble::ColorBuffer* RenderAble::RenderPipeline::consumeReadyColor() {
|
|
SpinLockGuard guard(&colorLock);
|
|
if(RenderAble::version_newer(readyColor->version, frontColor->version)) {
|
|
std::swap(frontColor, readyColor);
|
|
}
|
|
paintRequestPending = false;
|
|
dirtyRegion = QRegion();
|
|
return frontColor;
|
|
}
|
|
RenderEditGuard::RenderEditGuard(RenderData* data) : mData(data) {
|
|
}
|
|
RenderEditGuard::~RenderEditGuard() {
|
|
if(mData && mData->qPtr) mData->qPtr->markStateDirty();
|
|
}
|
|
void RenderAble::init(Plot* plot, QString layerName) {
|
|
if(layerName.isEmpty()) {
|
|
layerName = plot->mDefaultLayerName;
|
|
}
|
|
plot->mLayerMap[layerName]->mRenderAbles.append(this);
|
|
mPlot = plot;
|
|
if(!dPtr) dPtr = createRenderData();
|
|
delete dPtr->mRenderState;
|
|
delete dPtr->mRenderStateCache;
|
|
delete dPtr->mTempData;
|
|
delete dPtr->mTempDataCache;
|
|
dPtr->mRenderState = createRenderState();
|
|
dPtr->mRenderStateCache = createRenderState();
|
|
dPtr->mTempData = createTempData();
|
|
dPtr->mTempDataCache = createTempData();
|
|
dPtr->mRenderState->dPtr = dPtr;
|
|
dPtr->mRenderStateCache->dPtr = dPtr;
|
|
dPtr->qPtr = this;
|
|
dPtr->mRenderStateCache->version = 1;
|
|
if(mPlot) mPlot->markRenderStateDirty();
|
|
}
|
|
void RenderAble::markStateDirty() {
|
|
if(dPtr && dPtr->mRenderStateCache) ++dPtr->mRenderStateCache->version;
|
|
if(mPlot) mPlot->markRenderStateDirty();
|
|
}
|
|
bool RenderAble::ok() const {
|
|
return dPtr->mRenderStart && mPlot && !mPlot->mFirstResize && !mPlot->mFirstPrepareData;
|
|
}
|
|
|
|
RenderAble::~RenderAble(){
|
|
}
|
|
|
|
bool RenderAble::dectCycleRely() {
|
|
QQueue<RenderAble*> queue;
|
|
queue.enqueue(this);
|
|
while (!queue.isEmpty()) {
|
|
RenderAble* current = queue.dequeue();
|
|
QSet<RenderAble*> visited;
|
|
QSet<RenderAble*> recursionStack;
|
|
QVector<RenderAble*> path;
|
|
bool has = hasCycleRely(current, visited, recursionStack, path);
|
|
if(has){
|
|
return true;
|
|
}
|
|
}
|
|
qDebug() << this << " 检测成功!";
|
|
return false;
|
|
}
|
|
|
|
bool RenderAble::hasCycleRely(RenderAble* node, QSet<RenderAble*>& visited, QSet<RenderAble*>& recursionStack,
|
|
QVector<RenderAble*>& currentPath) {
|
|
if (!node) return false;
|
|
|
|
if (recursionStack.contains(node)) {
|
|
// 节点已经在当前递归路径中,检测到循环
|
|
qDebug() << "Cycle detected in path:";
|
|
|
|
// 打印循环依赖链
|
|
for (RenderAble* n : currentPath) {
|
|
qDebug() << n->mObjectName << "(" << n << ")->";
|
|
}
|
|
qDebug() << node; // 打印形成循环的节点
|
|
return true;
|
|
}
|
|
|
|
if (visited.contains(node)) {
|
|
// 节点已经被处理过,无需再次处理
|
|
return false;
|
|
}
|
|
|
|
// 标记当前节点为已访问
|
|
visited.insert(node);
|
|
// 将当前节点标记为递归路径中的节点
|
|
recursionStack.insert(node);
|
|
// 记录当前节点在路径中
|
|
currentPath.append(node);
|
|
|
|
// 递归检查所有子节点
|
|
for (RenderAble* child : node->mBeRelyList) {
|
|
if (hasCycleRely(child, visited, recursionStack, currentPath)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// 从递归路径中移除当前节点
|
|
recursionStack.remove(node);
|
|
// 从路径中移除当前节点
|
|
currentPath.removeLast();
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVector<QRgb> getTurboColorGradient() {
|
|
QVector<QRgb> colors;
|
|
// std::cout << "11111111111111111111111111111111111111" << std::endl;
|
|
// for (auto s : QDir(":/").entryList())
|
|
// {
|
|
// std::cout << "QDir=============" << s.toStdString() << std::endl;
|
|
// }
|
|
//
|
|
// std::cout << "11111111111111111111111111111111111111" << std::endl;
|
|
//
|
|
|
|
QFile file(":/turbo.colorMap");
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
std::ostringstream oss;
|
|
oss << file.errorString().toStdString() << " getTurboColorGradient2: Failed to open file" << LOG_POS_SIMPLE << std::endl;
|
|
Psc::fail_fast(oss.str());
|
|
return colors; // 返回一个空的 std::vector
|
|
}
|
|
|
|
QByteArray fileData = file.readAll();
|
|
file.close();
|
|
|
|
// 检查文件内容
|
|
if (fileData.size() != 768) {
|
|
qDebug() << "getTurboColorGradient2: File size is not as expected (768 bytes), got" << fileData.size();
|
|
return colors; // 返回一个空的 std::vector
|
|
}
|
|
|
|
// 确保每个颜色有 3 个字节 (RGB),总共有 256 个颜色
|
|
colors.reserve(256);
|
|
for (int i = 0; i < 256; ++i) {
|
|
uchar r = fileData[i * 3];
|
|
uchar g = fileData[i * 3 + 1];
|
|
uchar b = fileData[i * 3 + 2];
|
|
colors.push_back(qRgb(r, g, b));
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
SRC RenderState::src() {
|
|
return dPtr->mRenderState == this ? SRC::Render : SRC::Cache;
|
|
}
|
|
}
|