diff --git a/src/base/BitmapComposition.cpp b/src/base/BitmapComposition.cpp index 00c02552a7..7b3a629c80 100644 --- a/src/base/BitmapComposition.cpp +++ b/src/base/BitmapComposition.cpp @@ -22,103 +22,103 @@ namespace pag { BitmapComposition::~BitmapComposition() { - for (auto sequence : sequences) { - delete sequence; - } + for (auto sequence : sequences) { + delete sequence; + } } CompositionType BitmapComposition::type() const { - return CompositionType::Bitmap; + return CompositionType::Bitmap; } static bool IsEmptyBitmapFrame(BitmapFrame* frame) { - // There was a bug in PAGExporter that causes an empty frame being exported as 1x1 frame, so we - // need to identify this kind of empty frame here. - for (auto bitmap : frame->bitmaps) { - if (bitmap->x != 0 || bitmap->y != 0) { - return false; - } - if (bitmap->fileBytes->length() > 150) { - return false; - } + // There was a bug in PAGExporter that causes an empty frame being exported as 1x1 frame, so we + // need to identify this kind of empty frame here. + for (auto bitmap : frame->bitmaps) { + if (bitmap->x != 0 || bitmap->y != 0) { + return false; + } + if (bitmap->fileBytes->length() > 150) { + return false; + } - int width = 0; - int height = 0; - if (!WebPGetInfo(bitmap->fileBytes->data(), bitmap->fileBytes->length(), &width, &height)) { - LOGE("Get webP size fail."); - } - if (width > 1 || height > 1) { - return false; + int width = 0; + int height = 0; + if (!WebPGetInfo(bitmap->fileBytes->data(), bitmap->fileBytes->length(), &width, &height)) { + LOGE("Get webP size fail."); + } + if (width > 1 || height > 1) { + return false; + } } - } - return true; + return true; } static TimeRange MakeTimeRange(Frame start, Frame end, float timeScale) { - auto startFrame = static_cast(roundf(start * timeScale)); - auto endFrame = static_cast(roundf(end * timeScale)); - return {startFrame, endFrame}; + auto startFrame = static_cast(roundf(start * timeScale)); + auto endFrame = static_cast(roundf(end * timeScale)); + return {startFrame, endFrame}; } void BitmapComposition::updateStaticTimeRanges() { - staticTimeRanges = {}; - if (duration <= 1) { - return; - } - if (!sequences.empty()) { - Frame start = 0; - Frame end = 0; - size_t index = 0; - auto sequence = sequences[0]; - for (size_t i = 1; i < sequences.size(); i++) { - auto item = sequences[i]; - if (item->frameRate > sequence->frameRate) { - sequence = item; - } + staticTimeRanges = {}; + if (duration <= 1) { + return; } - float timeScale = frameRate / sequence->frameRate; - for (auto frame : sequence->frames) { - if (IsEmptyBitmapFrame(frame)) { - end = index; - } else { + if (!sequences.empty()) { + Frame start = 0; + Frame end = 0; + size_t index = 0; + auto sequence = sequences[0]; + for (size_t i = 1; i < sequences.size(); i++) { + auto item = sequences[i]; + if (item->frameRate > sequence->frameRate) { + sequence = item; + } + } + float timeScale = frameRate / sequence->frameRate; + for (auto frame : sequence->frames) { + if (IsEmptyBitmapFrame(frame)) { + end = index; + } else { + if (end > start) { + auto range = MakeTimeRange(start, end, timeScale); + staticTimeRanges.push_back(range); + } + start = end = index; + } + index++; + } if (end > start) { - auto range = MakeTimeRange(start, end, timeScale); - staticTimeRanges.push_back(range); + auto range = MakeTimeRange(start, end, timeScale); + staticTimeRanges.push_back(range); } - start = end = index; - } - index++; - } - if (end > start) { - auto range = MakeTimeRange(start, end, timeScale); - staticTimeRanges.push_back(range); + } else { + TimeRange range = {0, duration - 1}; + staticTimeRanges.push_back(range); } - } else { - TimeRange range = {0, duration - 1}; - staticTimeRanges.push_back(range); - } } bool BitmapComposition::hasImageContent() const { - return true; + return true; } bool BitmapComposition::verify() const { - if (!Composition::verify()) { - VerifyFailed(); - return false; - } - if (sequences.empty()) { - VerifyFailed(); - return false; - } - auto sequenceValid = [](BitmapSequence* sequence) { - return sequence != nullptr && sequence->verify(); - }; - if (!std::all_of(sequences.begin(), sequences.end(), sequenceValid)) { - VerifyFailed(); - return false; - } - return true; + if (!Composition::verify()) { + VerifyFailed(); + return false; + } + if (sequences.empty()) { + VerifyFailed(); + return false; + } + auto sequenceValid = [](BitmapSequence* sequence) { + return sequence != nullptr && sequence->verify(); + }; + if (!std::all_of(sequences.begin(), sequences.end(), sequenceValid)) { + VerifyFailed(); + return false; + } + return true; } } // namespace pag diff --git a/src/base/BitmapSequence.cpp b/src/base/BitmapSequence.cpp index 82fdb44062..6b607ad0b5 100644 --- a/src/base/BitmapSequence.cpp +++ b/src/base/BitmapSequence.cpp @@ -21,38 +21,40 @@ namespace pag { BitmapRect::~BitmapRect() { - delete fileBytes; + delete fileBytes; } BitmapFrame::~BitmapFrame() { - for (auto image : bitmaps) { - delete image; - } + for (auto image : bitmaps) { + delete image; + } } bool BitmapFrame::verify() const { - auto bitmapNotNull = [](BitmapRect* bitmap) { - return bitmap != nullptr && bitmap->fileBytes != nullptr; - }; - VerifyAndReturn(std::all_of(bitmaps.begin(), bitmaps.end(), bitmapNotNull)); + auto bitmapNotNull = [](BitmapRect* bitmap) { + return bitmap != nullptr && bitmap->fileBytes != nullptr; + }; + VerifyAndReturn(std::all_of(bitmaps.begin(), bitmaps.end(), bitmapNotNull)); } BitmapSequence::~BitmapSequence() { - for (auto frame : frames) { - delete frame; - } + for (auto frame : frames) { + delete frame; + } } bool BitmapSequence::verify() const { - if (!Sequence::verify() || frames.empty()) { - VerifyFailed(); - return false; - } - auto frameNotNull = [](BitmapFrame* frame) { return frame != nullptr && frame->verify(); }; - if (!std::all_of(frames.begin(), frames.end(), frameNotNull)) { - VerifyFailed(); - return false; - } - return true; + if (!Sequence::verify() || frames.empty()) { + VerifyFailed(); + return false; + } + auto frameNotNull = [](BitmapFrame* frame) { + return frame != nullptr && frame->verify(); + }; + if (!std::all_of(frames.begin(), frames.end(), frameNotNull)) { + VerifyFailed(); + return false; + } + return true; } } // namespace pag \ No newline at end of file diff --git a/src/base/ByteData.cpp b/src/base/ByteData.cpp index c3da82a69e..ab026f294a 100644 --- a/src/base/ByteData.cpp +++ b/src/base/ByteData.cpp @@ -21,52 +21,52 @@ namespace pag { std::unique_ptr ByteData::FromPath(const std::string& filePath) { - auto stream = Stream::MakeFromFile(filePath); - if (stream == nullptr) { - return nullptr; - } - auto data = ByteData::Make(stream->size()); - if (data == nullptr) { - return nullptr; - } - stream->read(data->data(), stream->size()); - return data; + auto stream = Stream::MakeFromFile(filePath); + if (stream == nullptr) { + return nullptr; + } + auto data = ByteData::Make(stream->size()); + if (data == nullptr) { + return nullptr; + } + stream->read(data->data(), stream->size()); + return data; } std::unique_ptr ByteData::MakeCopy(const void* bytes, size_t length) { - if (length == 0) { - return Make(0); - } - auto data = new (std::nothrow) uint8_t[length]; - if (data == nullptr) { - return nullptr; - } - memcpy(data, bytes, length); - auto byteData = new ByteData(data, length); - return std::unique_ptr(byteData); + if (length == 0) { + return Make(0); + } + auto data = new (std::nothrow) uint8_t[length]; + if (data == nullptr) { + return nullptr; + } + memcpy(data, bytes, length); + auto byteData = new ByteData(data, length); + return std::unique_ptr(byteData); } std::unique_ptr ByteData::MakeWithoutCopy(void* data, size_t length) { - if (length == 0) { - return Make(0); - } - auto byteData = new ByteData(reinterpret_cast(data), length, nullptr); - return std::unique_ptr(byteData); + if (length == 0) { + return Make(0); + } + auto byteData = new ByteData(reinterpret_cast(data), length, nullptr); + return std::unique_ptr(byteData); } std::unique_ptr ByteData::MakeAdopted(uint8_t* data, size_t length, - std::function releaseCallback) { - if (length == 0) { - data = nullptr; - } - auto byteData = new ByteData(data, length, releaseCallback); - return std::unique_ptr(byteData); + std::function releaseCallback) { + if (length == 0) { + data = nullptr; + } + auto byteData = new ByteData(data, length, releaseCallback); + return std::unique_ptr(byteData); } std::unique_ptr ByteData::Make(size_t length) { - auto data = length > 0 ? new (std::nothrow) uint8_t[length] : nullptr; - auto byteData = new ByteData(data, length); - return std::unique_ptr(byteData); + auto data = length > 0 ? new (std::nothrow) uint8_t[length] : nullptr; + auto byteData = new ByteData(data, length); + return std::unique_ptr(byteData); } } // namespace pag diff --git a/src/base/Composition.cpp b/src/base/Composition.cpp index d35c1f8024..3c09ec55b9 100644 --- a/src/base/Composition.cpp +++ b/src/base/Composition.cpp @@ -26,36 +26,36 @@ Composition::Composition() : uniqueID(UniqueID::Next()) { } Composition::~Composition() { - delete cache; - delete audioBytes; - for (auto& marker : audioMarkers) { - delete marker; - } + delete cache; + delete audioBytes; + for (auto& marker : audioMarkers) { + delete marker; + } } bool Composition::staticContent() const { - return staticTimeRanges.size() == 1 && staticTimeRanges.front().start == 0 && - staticTimeRanges.front().end == duration - 1; + return staticTimeRanges.size() == 1 && staticTimeRanges.front().start == 0 && + staticTimeRanges.front().end == duration - 1; } bool Composition::hasImageContent() const { - return false; + return false; } CompositionType Composition::type() const { - return CompositionType::Unknown; + return CompositionType::Unknown; } void Composition::updateStaticTimeRanges() { - TimeRange timeRange = {0, duration - 1}; - staticTimeRanges = {timeRange}; + TimeRange timeRange = {0, duration - 1}; + staticTimeRanges = {timeRange}; } bool Composition::verify() const { - if (audioBytes != nullptr && audioBytes->length() == 0) { - VerifyFailed(); - return false; - } - VerifyAndReturn(width > 0 && height > 0 && duration > 0 && frameRate > 0); + if (audioBytes != nullptr && audioBytes->length() == 0) { + VerifyFailed(); + return false; + } + VerifyAndReturn(width > 0 && height > 0 && duration > 0 && frameRate > 0); } } // namespace pag \ No newline at end of file diff --git a/src/base/File.cpp b/src/base/File.cpp index 08aaf4ae4e..613f5134cf 100644 --- a/src/base/File.cpp +++ b/src/base/File.cpp @@ -25,221 +25,221 @@ namespace pag { static std::mutex globalLocker = {}; static std::unordered_map> weakFileMap = - std::unordered_map>(); + std::unordered_map>(); static std::shared_ptr FindFileByPath(const std::string& filePath) { - std::lock_guard autoLock(globalLocker); - if (filePath.empty()) { - return nullptr; - } - auto result = weakFileMap.find(filePath); - if (result != weakFileMap.end()) { - auto& weak = result->second; - auto file = weak.lock(); - if (file) { - return file; - } - weakFileMap.erase(result); - if (weakFileMap.size() > 50) { // do cleaning. - std::vector needRemoveList = {}; - for (auto& item : weakFileMap) { - if (item.second.expired()) { - needRemoveList.push_back(item.first); + std::lock_guard autoLock(globalLocker); + if (filePath.empty()) { + return nullptr; + } + auto result = weakFileMap.find(filePath); + if (result != weakFileMap.end()) { + auto& weak = result->second; + auto file = weak.lock(); + if (file) { + return file; + } + weakFileMap.erase(result); + if (weakFileMap.size() > 50) { // do cleaning. + std::vector needRemoveList = {}; + for (auto& item : weakFileMap) { + if (item.second.expired()) { + needRemoveList.push_back(item.first); + } + } + for (auto& item : needRemoveList) { + weakFileMap.erase(item); + } } - } - for (auto& item : needRemoveList) { - weakFileMap.erase(item); - } } - } - return nullptr; + return nullptr; } std::shared_ptr File::Load(const std::string& filePath) { - auto byteData = ByteData::FromPath(filePath); - if (byteData == nullptr) { - return nullptr; - } - return pag::File::Load(byteData->data(), byteData->length(), filePath); + auto byteData = ByteData::FromPath(filePath); + if (byteData == nullptr) { + return nullptr; + } + return pag::File::Load(byteData->data(), byteData->length(), filePath); } uint16_t File::MaxSupportedTagLevel() { - return Codec::MaxSupportedTagLevel(); + return Codec::MaxSupportedTagLevel(); } std::shared_ptr File::Load(const void* bytes, size_t length, const std::string& filePath) { - auto file = FindFileByPath(filePath); - if (file != nullptr) { + auto file = FindFileByPath(filePath); + if (file != nullptr) { + return file; + } + file = Codec::Decode(bytes, static_cast(length), filePath); + if (file != nullptr) { + std::lock_guard autoLock(globalLocker); + std::weak_ptr weak = file; + weakFileMap.insert(std::make_pair(filePath, std::move(weak))); + } return file; - } - file = Codec::Decode(bytes, static_cast(length), filePath); - if (file != nullptr) { - std::lock_guard autoLock(globalLocker); - std::weak_ptr weak = file; - weakFileMap.insert(std::make_pair(filePath, std::move(weak))); - } - return file; } File::File(std::vector compositionList, std::vector imageList) : images(std::move(imageList)), compositions(std::move(compositionList)) { - mainComposition = compositions.back(); - scaledTimeRange.start = 0; - scaledTimeRange.end = mainComposition->duration; - rootLayer = PreComposeLayer::Wrap(mainComposition).release(); - updateEditables(mainComposition); - for (auto composition : compositions) { - if (composition->type() != CompositionType::Vector) { - _numLayers++; - continue; - } - for (auto layer : static_cast(composition)->layers) { - if (layer->type() == LayerType::PreCompose) { - continue; - } - _numLayers++; + mainComposition = compositions.back(); + scaledTimeRange.start = 0; + scaledTimeRange.end = mainComposition->duration; + rootLayer = PreComposeLayer::Wrap(mainComposition).release(); + updateEditables(mainComposition); + for (auto composition : compositions) { + if (composition->type() != CompositionType::Vector) { + _numLayers++; + continue; + } + for (auto layer : static_cast(composition)->layers) { + if (layer->type() == LayerType::PreCompose) { + continue; + } + _numLayers++; + } } - } } File::~File() { - for (auto& composition : compositions) { - delete composition; - } - for (auto& imageBytes : images) { - delete imageBytes; - } - delete rootLayer; + for (auto& composition : compositions) { + delete composition; + } + for (auto& imageBytes : images) { + delete imageBytes; + } + delete rootLayer; } void File::updateEditables(Composition* composition) { - if (composition->type() != CompositionType::Vector) { - return; - } - for (auto layer : static_cast(composition)->layers) { - if (layer->type() == LayerType::Text) { - auto textLayer = static_cast(layer); - // 多个预合成图层指向同一个预合成时,这个预合成里的文本图层需要排重. - auto result = std::find(textLayers.begin(), textLayers.end(), textLayer); - if (result == textLayers.end()) { - textLayers.push_back(textLayer); - } - } else if (layer->type() == LayerType::Image) { - auto imageLayer = static_cast(layer); - auto imageBytes = imageLayer->imageBytes; - bool found = false; - for (auto& list : imageLayers) { - if (list[0]->imageBytes == imageBytes) { - list.push_back(imageLayer); - found = true; - break; + if (composition->type() != CompositionType::Vector) { + return; + } + for (auto layer : static_cast(composition)->layers) { + if (layer->type() == LayerType::Text) { + auto textLayer = static_cast(layer); + // 多个预合成图层指向同一个预合成时,这个预合成里的文本图层需要排重. + auto result = std::find(textLayers.begin(), textLayers.end(), textLayer); + if (result == textLayers.end()) { + textLayers.push_back(textLayer); + } + } else if (layer->type() == LayerType::Image) { + auto imageLayer = static_cast(layer); + auto imageBytes = imageLayer->imageBytes; + bool found = false; + for (auto& list : imageLayers) { + if (list[0]->imageBytes == imageBytes) { + list.push_back(imageLayer); + found = true; + break; + } + } + if (!found) { + std::vector list = {imageLayer}; + imageLayers.push_back(list); + } + } else if (layer->type() == LayerType::PreCompose) { + updateEditables(static_cast(layer)->composition); } - } - if (!found) { - std::vector list = {imageLayer}; - imageLayers.push_back(list); - } - } else if (layer->type() == LayerType::PreCompose) { - updateEditables(static_cast(layer)->composition); } - } } int64_t File::duration() const { - return mainComposition->duration; + return mainComposition->duration; } float File::frameRate() const { - return mainComposition->frameRate; + return mainComposition->frameRate; } Color File::backgroundColor() const { - return mainComposition->backgroundColor; + return mainComposition->backgroundColor; } int32_t File::width() const { - return mainComposition->width; + return mainComposition->width; } int32_t File::height() const { - return mainComposition->height; + return mainComposition->height; } uint16_t File::tagLevel() const { - return _tagLevel; + return _tagLevel; } int File::numLayers() const { - return _numLayers; + return _numLayers; } int File::numTexts() const { - return static_cast(textLayers.size()); + return static_cast(textLayers.size()); } int File::numImages() const { - return static_cast(imageLayers.size()); + return static_cast(imageLayers.size()); } int File::numVideos() const { - unsigned int count = 0; - for (auto composition : compositions) { - if (composition->type() == CompositionType::Video) { - count++; + unsigned int count = 0; + for (auto composition : compositions) { + if (composition->type() == CompositionType::Video) { + count++; + } } - } - return static_cast(count); + return static_cast(count); } TextDocumentHandle File::getTextData(int index) const { - if (index < 0 || static_cast(index) >= textLayers.size()) { - return nullptr; - } - auto textDocument = textLayers[index]->getTextDocument(); - auto textData = new TextDocument(); - *textData = *textDocument; - return TextDocumentHandle(textData); + if (index < 0 || static_cast(index) >= textLayers.size()) { + return nullptr; + } + auto textDocument = textLayers[index]->getTextDocument(); + auto textData = new TextDocument(); + *textData = *textDocument; + return TextDocumentHandle(textData); } PreComposeLayer* File::getRootLayer() const { - return rootLayer; + return rootLayer; } TextLayer* File::getTextAt(int index) const { - if (index < 0 || static_cast(index) >= textLayers.size()) { - return nullptr; - } - return textLayers[index]; + if (index < 0 || static_cast(index) >= textLayers.size()) { + return nullptr; + } + return textLayers[index]; } int File::getEditableIndex(TextLayer* textLayer) const { - auto result = std::find(textLayers.begin(), textLayers.end(), textLayer); - if (result != textLayers.end()) { - return static_cast(result - textLayers.begin()); - } - return -1; + auto result = std::find(textLayers.begin(), textLayers.end(), textLayer); + if (result != textLayers.end()) { + return static_cast(result - textLayers.begin()); + } + return -1; } int File::getEditableIndex(pag::ImageLayer* imageLayer) const { - int index = 0; - for (auto& layers : imageLayers) { - auto result = std::find(layers.begin(), layers.end(), imageLayer); - if (result != layers.end()) { - return index; + int index = 0; + for (auto& layers : imageLayers) { + auto result = std::find(layers.begin(), layers.end(), imageLayer); + if (result != layers.end()) { + return index; + } + index++; } - index++; - } - return -1; + return -1; } std::vector File::getImageAt(int index) const { - if (index < 0 || static_cast(index) >= imageLayers.size()) { - return {}; - } - return imageLayers[index]; + if (index < 0 || static_cast(index) >= imageLayers.size()) { + return {}; + } + return imageLayers[index]; } bool File::hasScaledTimeRange() const { - return scaledTimeRange.start != 0 || scaledTimeRange.end != mainComposition->duration; + return scaledTimeRange.start != 0 || scaledTimeRange.end != mainComposition->duration; } } // namespace pag diff --git a/src/base/GradientColor.cpp b/src/base/GradientColor.cpp index cd1a26799b..3262701182 100644 --- a/src/base/GradientColor.cpp +++ b/src/base/GradientColor.cpp @@ -21,19 +21,19 @@ namespace pag { void GradientColor::interpolate(const GradientColor& other, GradientColor* result, float t) { - result->alphaStops = alphaStops; - result->colorStops = colorStops; - auto alphaCount = std::min(alphaStops.size(), other.alphaStops.size()); - for (size_t i = 0; i < alphaCount; i++) { - auto start = alphaStops[i].opacity; - auto end = other.alphaStops[i].opacity; - result->alphaStops[i].opacity = Interpolate(start, end, t); - } - auto colorCount = std::min(colorStops.size(), other.colorStops.size()); - for (size_t i = 0; i < colorCount; i++) { - auto start = colorStops[i].color; - auto end = other.colorStops[i].color; - result->colorStops[i].color = Interpolate(start, end, t); - } + result->alphaStops = alphaStops; + result->colorStops = colorStops; + auto alphaCount = std::min(alphaStops.size(), other.alphaStops.size()); + for (size_t i = 0; i < alphaCount; i++) { + auto start = alphaStops[i].opacity; + auto end = other.alphaStops[i].opacity; + result->alphaStops[i].opacity = Interpolate(start, end, t); + } + auto colorCount = std::min(colorStops.size(), other.colorStops.size()); + for (size_t i = 0; i < colorCount; i++) { + auto start = colorStops[i].color; + auto end = other.colorStops[i].color; + result->colorStops[i].color = Interpolate(start, end, t); + } } } // namespace pag diff --git a/src/base/ImageBytes.cpp b/src/base/ImageBytes.cpp index 50218a4ea2..8eea4fda38 100644 --- a/src/base/ImageBytes.cpp +++ b/src/base/ImageBytes.cpp @@ -25,12 +25,12 @@ ImageBytes::ImageBytes() : uniqueID(UniqueID::Next()) { } ImageBytes::~ImageBytes() { - delete cache; - delete fileBytes; + delete cache; + delete fileBytes; } bool ImageBytes::verify() const { - VerifyAndReturn(fileBytes != nullptr && fileBytes->length() > 0 && scaleFactor > 0 && width > 0 && - height > 0); + VerifyAndReturn(fileBytes != nullptr && fileBytes->length() > 0 && scaleFactor > 0 && width > 0 && + height > 0); } } // namespace pag diff --git a/src/base/ImageLayer.cpp b/src/base/ImageLayer.cpp index 85b7ec877e..521a8ce504 100644 --- a/src/base/ImageLayer.cpp +++ b/src/base/ImageLayer.cpp @@ -21,18 +21,18 @@ namespace pag { ImageFillRule::~ImageFillRule() { - delete timeRemap; + delete timeRemap; } ImageLayer::~ImageLayer() { - delete imageFillRule; + delete imageFillRule; } bool ImageLayer::verify() const { - if (!Layer::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(imageBytes != nullptr); + if (!Layer::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(imageBytes != nullptr); } } // namespace pag diff --git a/src/base/Layer.cpp b/src/base/Layer.cpp index eda31c48b2..ce0fdb14b0 100644 --- a/src/base/Layer.cpp +++ b/src/base/Layer.cpp @@ -26,113 +26,113 @@ Layer::Layer() : uniqueID(UniqueID::Next()) { } Layer::~Layer() { - delete cache; - delete transform; - delete timeRemap; - for (auto& mask : masks) { - delete mask; - } - for (auto& effect : effects) { - delete effect; - } - for (auto& style : layerStyles) { - delete style; - } - for (auto& marker : markers) { - delete marker; - } + delete cache; + delete transform; + delete timeRemap; + for (auto& mask : masks) { + delete mask; + } + for (auto& effect : effects) { + delete effect; + } + for (auto& style : layerStyles) { + delete style; + } + for (auto& marker : markers) { + delete marker; + } } void Layer::excludeVaryingRanges(std::vector* timeRanges) { - transform->excludeVaryingRanges(timeRanges); - if (timeRemap != nullptr) { - timeRemap->excludeVaryingRanges(timeRanges); - } - for (auto& mask : masks) { - mask->excludeVaryingRanges(timeRanges); - } - for (auto& effect : effects) { - effect->excludeVaryingRanges(timeRanges); - } - for (auto& layerStyle : layerStyles) { - layerStyle->excludeVaryingRanges(timeRanges); - } + transform->excludeVaryingRanges(timeRanges); + if (timeRemap != nullptr) { + timeRemap->excludeVaryingRanges(timeRanges); + } + for (auto& mask : masks) { + mask->excludeVaryingRanges(timeRanges); + } + for (auto& effect : effects) { + effect->excludeVaryingRanges(timeRanges); + } + for (auto& layerStyle : layerStyles) { + layerStyle->excludeVaryingRanges(timeRanges); + } } bool Layer::verify() const { - if (containingComposition == nullptr || duration <= 0 || transform == nullptr) { - VerifyFailed(); - return false; - } - if (!transform->verify()) { - VerifyFailed(); - return false; - } - for (auto mask : masks) { - if (mask == nullptr || !mask->verify()) { - VerifyFailed(); - return false; - } - } - return verifyExtra(); + if (containingComposition == nullptr || duration <= 0 || transform == nullptr) { + VerifyFailed(); + return false; + } + if (!transform->verify()) { + VerifyFailed(); + return false; + } + for (auto mask : masks) { + if (mask == nullptr || !mask->verify()) { + VerifyFailed(); + return false; + } + } + return verifyExtra(); } bool Layer::verifyExtra() const { - for (auto layerStyle : layerStyles) { - if (layerStyle == nullptr || !layerStyle->verify()) { - VerifyFailed(); - return false; - } - } - for (auto effect : effects) { - if (effect == nullptr || !effect->verify()) { - VerifyFailed(); - return false; - } - } - for (auto& marker : markers) { - if (marker == nullptr || marker->comment.empty()) { - VerifyFailed(); - return false; - } - } - return true; + for (auto layerStyle : layerStyles) { + if (layerStyle == nullptr || !layerStyle->verify()) { + VerifyFailed(); + return false; + } + } + for (auto effect : effects) { + if (effect == nullptr || !effect->verify()) { + VerifyFailed(); + return false; + } + } + for (auto& marker : markers) { + if (marker == nullptr || marker->comment.empty()) { + VerifyFailed(); + return false; + } + } + return true; } Point Layer::getMaxScaleFactor() { - auto maxScale = Point::Make(1, 1); - auto property = transform->scale; - if (property->animatable()) { - auto keyframes = static_cast*>(property)->keyframes; - float scaleX = fabs(keyframes[0]->startValue.x); - float scaleY = fabs(keyframes[0]->startValue.y); - for (auto& keyframe : keyframes) { - auto x = fabs(keyframe->endValue.x); - auto y = fabs(keyframe->endValue.y); - if (scaleX < x) { - scaleX = x; - } - if (scaleY < y) { - scaleY = y; - } - } - maxScale.x = scaleX; - maxScale.y = scaleY; - } else { - maxScale.x = fabs(property->value.x); - maxScale.y = fabs(property->value.y); - } - if (parent != nullptr) { - auto parentScale = parent->getMaxScaleFactor(); - maxScale.x *= parentScale.x; - maxScale.y *= parentScale.y; - } - return maxScale; + auto maxScale = Point::Make(1, 1); + auto property = transform->scale; + if (property->animatable()) { + auto keyframes = static_cast*>(property)->keyframes; + float scaleX = fabs(keyframes[0]->startValue.x); + float scaleY = fabs(keyframes[0]->startValue.y); + for (auto& keyframe : keyframes) { + auto x = fabs(keyframe->endValue.x); + auto y = fabs(keyframe->endValue.y); + if (scaleX < x) { + scaleX = x; + } + if (scaleY < y) { + scaleY = y; + } + } + maxScale.x = scaleX; + maxScale.y = scaleY; + } else { + maxScale.x = fabs(property->value.x); + maxScale.y = fabs(property->value.y); + } + if (parent != nullptr) { + auto parentScale = parent->getMaxScaleFactor(); + maxScale.x *= parentScale.x; + maxScale.y *= parentScale.y; + } + return maxScale; } TimeRange Layer::visibleRange() { - TimeRange range = {startTime, startTime + duration - 1}; - return range; + TimeRange range = {startTime, startTime + duration - 1}; + return range; } } // namespace pag diff --git a/src/base/MaskData.cpp b/src/base/MaskData.cpp index 1c706ea3aa..2151653e8f 100644 --- a/src/base/MaskData.cpp +++ b/src/base/MaskData.cpp @@ -21,18 +21,18 @@ namespace pag { MaskData::~MaskData() { - delete maskPath; - delete maskOpacity; - delete maskExpansion; + delete maskPath; + delete maskOpacity; + delete maskExpansion; } void MaskData::excludeVaryingRanges(std::vector* timeRanges) const { - maskPath->excludeVaryingRanges(timeRanges); - maskOpacity->excludeVaryingRanges(timeRanges); - maskExpansion->excludeVaryingRanges(timeRanges); + maskPath->excludeVaryingRanges(timeRanges); + maskOpacity->excludeVaryingRanges(timeRanges); + maskExpansion->excludeVaryingRanges(timeRanges); } bool MaskData::verify() const { - VerifyAndReturn(maskPath != nullptr); + VerifyAndReturn(maskPath != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/Matrix.cpp b/src/base/Matrix.cpp index d4e2a1a438..9bd062718f 100644 --- a/src/base/Matrix.cpp +++ b/src/base/Matrix.cpp @@ -22,453 +22,453 @@ namespace pag { void Matrix::reset() { - values[SCALE_X] = values[SCALE_Y] = values[PERSP_2] = 1; - values[SKEW_X] = values[SKEW_Y] = values[TRANS_X] = values[TRANS_Y] = values[PERSP_0] = - values[PERSP_1] = 0; + values[SCALE_X] = values[SCALE_Y] = values[PERSP_2] = 1; + values[SKEW_X] = values[SKEW_Y] = values[TRANS_X] = values[TRANS_Y] = values[PERSP_0] = + values[PERSP_1] = 0; } bool operator==(const Matrix& a, const Matrix& b) { - const float* ma = a.values; - const float* mb = b.values; - return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && ma[3] == mb[3] && ma[4] == mb[4] && - ma[5] == mb[5] && ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; + const float* ma = a.values; + const float* mb = b.values; + return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && ma[3] == mb[3] && ma[4] == mb[4] && + ma[5] == mb[5] && ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; } void Matrix::setAll(float scaleX, float skewX, float transX, float skewY, float scaleY, float transY, float persp0, float persp1, float persp2) { - values[SCALE_X] = scaleX; - values[SKEW_X] = skewX; - values[TRANS_X] = transX; - values[SKEW_Y] = skewY; - values[SCALE_Y] = scaleY; - values[TRANS_Y] = transY; - values[PERSP_0] = persp0; - values[PERSP_1] = persp1; - values[PERSP_2] = persp2; + values[SCALE_X] = scaleX; + values[SKEW_X] = skewX; + values[TRANS_X] = transX; + values[SKEW_Y] = skewY; + values[SCALE_Y] = scaleY; + values[TRANS_Y] = transY; + values[PERSP_0] = persp0; + values[PERSP_1] = persp1; + values[PERSP_2] = persp2; } void Matrix::setAffine(float a, float b, float c, float d, float tx, float ty) { - values[SCALE_X] = a; - values[SKEW_X] = c; - values[TRANS_X] = tx; - values[SKEW_Y] = b; - values[SCALE_Y] = d; - values[TRANS_Y] = ty; - values[PERSP_0] = 0; - values[PERSP_1] = 0; - values[PERSP_2] = 1; + values[SCALE_X] = a; + values[SKEW_X] = c; + values[TRANS_X] = tx; + values[SKEW_Y] = b; + values[SCALE_Y] = d; + values[TRANS_Y] = ty; + values[PERSP_0] = 0; + values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::setTranslate(float dx, float dy) { - if ((dx != 0) | (dy != 0)) { - values[TRANS_X] = dx; - values[TRANS_Y] = dy; - - values[SCALE_X] = values[SCALE_Y] = values[PERSP_2] = 1; - values[SKEW_X] = values[SKEW_Y] = values[PERSP_0] = values[PERSP_1] = 0; - } else { - this->reset(); - } + if ((dx != 0) | (dy != 0)) { + values[TRANS_X] = dx; + values[TRANS_Y] = dy; + + values[SCALE_X] = values[SCALE_Y] = values[PERSP_2] = 1; + values[SKEW_X] = values[SKEW_Y] = values[PERSP_0] = values[PERSP_1] = 0; + } else { + this->reset(); + } } static inline float sdot(float a, float b, float c, float d) { - return a * b + c * d; + return a * b + c * d; } void Matrix::preTranslate(float dx, float dy) { - values[TRANS_X] += sdot(values[SCALE_X], dx, values[SKEW_X], dy); - values[TRANS_Y] += sdot(values[SKEW_Y], dx, values[SCALE_Y], dy); + values[TRANS_X] += sdot(values[SCALE_X], dx, values[SKEW_X], dy); + values[TRANS_Y] += sdot(values[SKEW_Y], dx, values[SCALE_Y], dy); } void Matrix::postTranslate(float dx, float dy) { - values[TRANS_X] += dx; - values[TRANS_Y] += dy; + values[TRANS_X] += dx; + values[TRANS_Y] += dy; } void Matrix::setScaleTranslate(float sx, float sy, float tx, float ty) { - values[SCALE_X] = sx; - values[SKEW_X] = 0; - values[TRANS_X] = tx; - - values[SKEW_Y] = 0; - values[SCALE_Y] = sy; - values[TRANS_Y] = ty; - - values[PERSP_0] = 0; - values[PERSP_1] = 0; - values[PERSP_2] = 1; -} - -void Matrix::setScale(float sx, float sy, float px, float py) { - if (1 == sx && 1 == sy) { - this->reset(); - } else { values[SCALE_X] = sx; values[SKEW_X] = 0; - values[TRANS_X] = 0; + values[TRANS_X] = tx; values[SKEW_Y] = 0; values[SCALE_Y] = sy; - values[TRANS_Y] = 0; + values[TRANS_Y] = ty; values[PERSP_0] = 0; values[PERSP_1] = 0; values[PERSP_2] = 1; - this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py); - } } -void Matrix::setScale(float sx, float sy) { - if (1 == sx && 1 == sy) { - this->reset(); - } else { - values[SCALE_X] = sx; - values[SCALE_Y] = sy; - values[PERSP_2] = 1; - - values[TRANS_X] = values[TRANS_Y] = values[SKEW_X] = values[SKEW_Y] = values[PERSP_0] = +void Matrix::setScale(float sx, float sy, float px, float py) { + if (1 == sx && 1 == sy) { + this->reset(); + } else { + values[SCALE_X] = sx; + values[SKEW_X] = 0; + values[TRANS_X] = 0; + + values[SKEW_Y] = 0; + values[SCALE_Y] = sy; + values[TRANS_Y] = 0; + + values[PERSP_0] = 0; values[PERSP_1] = 0; - } + values[PERSP_2] = 1; + this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py); + } +} + +void Matrix::setScale(float sx, float sy) { + if (1 == sx && 1 == sy) { + this->reset(); + } else { + values[SCALE_X] = sx; + values[SCALE_Y] = sy; + values[PERSP_2] = 1; + + values[TRANS_X] = values[TRANS_Y] = values[SKEW_X] = values[SKEW_Y] = values[PERSP_0] = + values[PERSP_1] = 0; + } } void Matrix::preScale(float sx, float sy, float px, float py) { - if (1 == sx && 1 == sy) { - return; - } + if (1 == sx && 1 == sy) { + return; + } - Matrix m = {}; - m.setScale(sx, sy, px, py); - this->preConcat(m); + Matrix m = {}; + m.setScale(sx, sy, px, py); + this->preConcat(m); } void Matrix::preScale(float sx, float sy) { - if (1 == sx && 1 == sy) { - return; - } - values[SCALE_X] *= sx; - values[SKEW_Y] *= sx; - values[PERSP_0] *= sx; + if (1 == sx && 1 == sy) { + return; + } + values[SCALE_X] *= sx; + values[SKEW_Y] *= sx; + values[PERSP_0] *= sx; - values[SKEW_X] *= sy; - values[SCALE_Y] *= sy; - values[PERSP_1] *= sy; + values[SKEW_X] *= sy; + values[SCALE_Y] *= sy; + values[PERSP_1] *= sy; } void Matrix::postScale(float sx, float sy, float px, float py) { - if (1 == sx && 1 == sy) { - return; - } - Matrix m = {}; - m.setScale(sx, sy, px, py); - this->postConcat(m); + if (1 == sx && 1 == sy) { + return; + } + Matrix m = {}; + m.setScale(sx, sy, px, py); + this->postConcat(m); } void Matrix::postScale(float sx, float sy) { - if (1 == sx && 1 == sy) { - return; - } - Matrix m = {}; - m.setScale(sx, sy); - this->postConcat(m); + if (1 == sx && 1 == sy) { + return; + } + Matrix m = {}; + m.setScale(sx, sy); + this->postConcat(m); } void Matrix::setSinCos(float sinV, float cosV, float px, float py) { - const float oneMinusCosV = 1 - cosV; + const float oneMinusCosV = 1 - cosV; - values[SCALE_X] = cosV; - values[SKEW_X] = -sinV; - values[TRANS_X] = sdot(sinV, py, oneMinusCosV, px); + values[SCALE_X] = cosV; + values[SKEW_X] = -sinV; + values[TRANS_X] = sdot(sinV, py, oneMinusCosV, px); - values[SKEW_Y] = sinV; - values[SCALE_Y] = cosV; - values[TRANS_Y] = sdot(-sinV, px, oneMinusCosV, py); + values[SKEW_Y] = sinV; + values[SCALE_Y] = cosV; + values[TRANS_Y] = sdot(-sinV, px, oneMinusCosV, py); - values[PERSP_0] = values[PERSP_1] = 0; - values[PERSP_2] = 1; + values[PERSP_0] = values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::setSinCos(float sinV, float cosV) { - values[SCALE_X] = cosV; - values[SKEW_X] = -sinV; - values[TRANS_X] = 0; + values[SCALE_X] = cosV; + values[SKEW_X] = -sinV; + values[TRANS_X] = 0; - values[SKEW_Y] = sinV; - values[SCALE_Y] = cosV; - values[TRANS_Y] = 0; + values[SKEW_Y] = sinV; + values[SCALE_Y] = cosV; + values[TRANS_Y] = 0; - values[PERSP_0] = values[PERSP_1] = 0; - values[PERSP_2] = 1; + values[PERSP_0] = values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::setRotate(float degrees, float px, float py) { - float rad = DegreesToRadians(degrees); - this->setSinCos(SinSnapToZero(rad), CosSnapToZero(rad), px, py); + float rad = DegreesToRadians(degrees); + this->setSinCos(SinSnapToZero(rad), CosSnapToZero(rad), px, py); } void Matrix::setRotate(float degrees) { - float rad = DegreesToRadians(degrees); - this->setSinCos(SinSnapToZero(rad), CosSnapToZero(rad)); + float rad = DegreesToRadians(degrees); + this->setSinCos(SinSnapToZero(rad), CosSnapToZero(rad)); } void Matrix::preRotate(float degrees, float px, float py) { - Matrix m = {}; - m.setRotate(degrees, px, py); - this->preConcat(m); + Matrix m = {}; + m.setRotate(degrees, px, py); + this->preConcat(m); } void Matrix::preRotate(float degrees) { - Matrix m = {}; - m.setRotate(degrees); - this->preConcat(m); + Matrix m = {}; + m.setRotate(degrees); + this->preConcat(m); } void Matrix::postRotate(float degrees, float px, float py) { - Matrix m = {}; - m.setRotate(degrees, px, py); - this->postConcat(m); + Matrix m = {}; + m.setRotate(degrees, px, py); + this->postConcat(m); } void Matrix::postRotate(float degrees) { - Matrix m = {}; - m.setRotate(degrees); - this->postConcat(m); + Matrix m = {}; + m.setRotate(degrees); + this->postConcat(m); } void Matrix::setSkew(float sx, float sy, float px, float py) { - values[SCALE_X] = 1; - values[SKEW_X] = sx; - values[TRANS_X] = -sx * py; + values[SCALE_X] = 1; + values[SKEW_X] = sx; + values[TRANS_X] = -sx * py; - values[SKEW_Y] = sy; - values[SCALE_Y] = 1; - values[TRANS_Y] = -sy * px; + values[SKEW_Y] = sy; + values[SCALE_Y] = 1; + values[TRANS_Y] = -sy * px; - values[PERSP_0] = values[PERSP_1] = 0; - values[PERSP_2] = 1; + values[PERSP_0] = values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::setSkew(float sx, float sy) { - values[SCALE_X] = 1; - values[SKEW_X] = sx; - values[TRANS_X] = 0; + values[SCALE_X] = 1; + values[SKEW_X] = sx; + values[TRANS_X] = 0; - values[SKEW_Y] = sy; - values[SCALE_Y] = 1; - values[TRANS_Y] = 0; + values[SKEW_Y] = sy; + values[SCALE_Y] = 1; + values[TRANS_Y] = 0; - values[PERSP_0] = values[PERSP_1] = 0; - values[PERSP_2] = 1; + values[PERSP_0] = values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::preSkew(float sx, float sy, float px, float py) { - Matrix m = {}; - m.setSkew(sx, sy, px, py); - this->preConcat(m); + Matrix m = {}; + m.setSkew(sx, sy, px, py); + this->preConcat(m); } void Matrix::preSkew(float sx, float sy) { - Matrix m = {}; - m.setSkew(sx, sy); - this->preConcat(m); + Matrix m = {}; + m.setSkew(sx, sy); + this->preConcat(m); } void Matrix::postSkew(float sx, float sy, float px, float py) { - Matrix m = {}; - m.setSkew(sx, sy, px, py); - this->postConcat(m); + Matrix m = {}; + m.setSkew(sx, sy, px, py); + this->postConcat(m); } void Matrix::postSkew(float sx, float sy) { - Matrix m = {}; - m.setSkew(sx, sy); - this->postConcat(m); + Matrix m = {}; + m.setSkew(sx, sy); + this->postConcat(m); } void Matrix::setConcat(const Matrix& first, const Matrix& second) { - auto& matA = first.values; - auto& matB = second.values; - auto a = matB[SCALE_X] * matA[SCALE_X]; - auto b = 0.0; - auto c = 0.0; - auto d = matB[SCALE_Y] * matA[SCALE_Y]; - auto tx = matB[TRANS_X] * matA[SCALE_X] + matA[TRANS_X]; - auto ty = matB[TRANS_Y] * matA[SCALE_Y] + matA[TRANS_Y]; - - if (matB[SKEW_Y] != 0.0 || matB[SKEW_X] != 0.0 || matA[SKEW_Y] != 0.0 || matA[SKEW_X] != 0.0) { - a += matB[SKEW_Y] * matA[SKEW_X]; - d += matB[SKEW_X] * matA[SKEW_Y]; - b += matB[SCALE_X] * matA[SKEW_Y] + matB[SKEW_Y] * matA[SCALE_Y]; - c += matB[SKEW_X] * matA[SCALE_X] + matB[SCALE_Y] * matA[SKEW_X]; - tx += matB[TRANS_Y] * matA[SKEW_X]; - ty += matB[TRANS_X] * matA[SKEW_Y]; - } - - values[SCALE_X] = a; - values[SKEW_Y] = b; - values[SKEW_X] = c; - values[SCALE_Y] = d; - values[TRANS_X] = tx; - values[TRANS_Y] = ty; - values[PERSP_0] = 0; - values[PERSP_1] = 0; - values[PERSP_2] = 1; + auto& matA = first.values; + auto& matB = second.values; + auto a = matB[SCALE_X] * matA[SCALE_X]; + auto b = 0.0; + auto c = 0.0; + auto d = matB[SCALE_Y] * matA[SCALE_Y]; + auto tx = matB[TRANS_X] * matA[SCALE_X] + matA[TRANS_X]; + auto ty = matB[TRANS_Y] * matA[SCALE_Y] + matA[TRANS_Y]; + + if (matB[SKEW_Y] != 0.0 || matB[SKEW_X] != 0.0 || matA[SKEW_Y] != 0.0 || matA[SKEW_X] != 0.0) { + a += matB[SKEW_Y] * matA[SKEW_X]; + d += matB[SKEW_X] * matA[SKEW_Y]; + b += matB[SCALE_X] * matA[SKEW_Y] + matB[SKEW_Y] * matA[SCALE_Y]; + c += matB[SKEW_X] * matA[SCALE_X] + matB[SCALE_Y] * matA[SKEW_X]; + tx += matB[TRANS_Y] * matA[SKEW_X]; + ty += matB[TRANS_X] * matA[SKEW_Y]; + } + + values[SCALE_X] = a; + values[SKEW_Y] = b; + values[SKEW_X] = c; + values[SCALE_Y] = d; + values[TRANS_X] = tx; + values[TRANS_Y] = ty; + values[PERSP_0] = 0; + values[PERSP_1] = 0; + values[PERSP_2] = 1; } void Matrix::preConcat(const Matrix& mat) { - // check for identity first, so we don't do a needless copy of ourselves - // to ourselves inside setConcat() - if (!mat.isIdentity()) { - this->setConcat(*this, mat); - } + // check for identity first, so we don't do a needless copy of ourselves + // to ourselves inside setConcat() + if (!mat.isIdentity()) { + this->setConcat(*this, mat); + } } void Matrix::postConcat(const Matrix& mat) { - // check for identity first, so we don't do a needless copy of ourselves - // to ourselves inside setConcat() - if (!mat.isIdentity()) { - this->setConcat(mat, *this); - } + // check for identity first, so we don't do a needless copy of ourselves + // to ourselves inside setConcat() + if (!mat.isIdentity()) { + this->setConcat(mat, *this); + } } bool Matrix::invertible() const { - float determinant = values[SCALE_X] * values[SCALE_Y] - values[SKEW_Y] * values[SKEW_X]; - return !(FloatNearlyZero(determinant, FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO)); + float determinant = values[SCALE_X] * values[SCALE_Y] - values[SKEW_Y] * values[SKEW_X]; + return !(FloatNearlyZero(determinant, FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO)); } bool Matrix::invertNonIdentity(Matrix* inverse) const { - auto a = values[SCALE_X]; - auto d = values[SCALE_Y]; - auto c = values[SKEW_X]; - auto b = values[SKEW_Y]; - auto tx = values[TRANS_X]; - auto ty = values[TRANS_Y]; - - if (b == 0 && c == 0) { - if (a == 0 || d == 0) { - return false; + auto a = values[SCALE_X]; + auto d = values[SCALE_Y]; + auto c = values[SKEW_X]; + auto b = values[SKEW_Y]; + auto tx = values[TRANS_X]; + auto ty = values[TRANS_Y]; + + if (b == 0 && c == 0) { + if (a == 0 || d == 0) { + return false; + } + a = 1 / a; + d = 1 / d; + tx = -a * tx; + ty = -d * ty; + inverse->setAffine(a, b, c, d, tx, ty); + return true; } - a = 1 / a; - d = 1 / d; - tx = -a * tx; - ty = -d * ty; + float determinant = a * d - b * c; + if (FloatNearlyZero(determinant, FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO)) { + return false; + } + determinant = 1 / determinant; + a = d * determinant; + b = -b * determinant; + c = -c * determinant; + d = values[SCALE_X] * determinant; + tx = -(a * values[TRANS_X] + c * values[TRANS_Y]); + ty = -(b * values[TRANS_X] + d * values[TRANS_Y]); inverse->setAffine(a, b, c, d, tx, ty); return true; - } - float determinant = a * d - b * c; - if (FloatNearlyZero(determinant, FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO)) { - return false; - } - determinant = 1 / determinant; - a = d * determinant; - b = -b * determinant; - c = -c * determinant; - d = values[SCALE_X] * determinant; - tx = -(a * values[TRANS_X] + c * values[TRANS_Y]); - ty = -(b * values[TRANS_X] + d * values[TRANS_Y]); - inverse->setAffine(a, b, c, d, tx, ty); - return true; } void Matrix::mapPoints(Point dst[], const Point src[], int count) const { - auto tx = values[TRANS_X]; - auto ty = values[TRANS_Y]; - auto sx = values[SCALE_X]; - auto sy = values[SCALE_Y]; - auto kx = values[SKEW_X]; - auto ky = values[SKEW_Y]; - for (int i = 0; i < count; i++) { - auto x = src[i].x * sx + src[i].y * kx + tx; - auto y = src[i].x * ky + src[i].y * sy + ty; - dst[i].set(x, y); - } + auto tx = values[TRANS_X]; + auto ty = values[TRANS_Y]; + auto sx = values[SCALE_X]; + auto sy = values[SCALE_Y]; + auto kx = values[SKEW_X]; + auto ky = values[SKEW_Y]; + for (int i = 0; i < count; i++) { + auto x = src[i].x * sx + src[i].y * kx + tx; + auto y = src[i].x * ky + src[i].y * sy + ty; + dst[i].set(x, y); + } } void Matrix::mapXY(float x, float y, Point* result) const { - auto tx = values[TRANS_X]; - auto ty = values[TRANS_Y]; - auto sx = values[SCALE_X]; - auto sy = values[SCALE_Y]; - auto kx = values[SKEW_X]; - auto ky = values[SKEW_Y]; - result->set(x * sx + y * kx + tx, x * ky + y * sy + ty); + auto tx = values[TRANS_X]; + auto ty = values[TRANS_Y]; + auto sx = values[SCALE_X]; + auto sy = values[SCALE_Y]; + auto kx = values[SKEW_X]; + auto ky = values[SKEW_Y]; + result->set(x * sx + y * kx + tx, x * ky + y * sy + ty); } void Matrix::mapRect(Rect* dst, const Rect& src) const { - Point quad[4]; - quad[0].set(src.left, src.top); - quad[1].set(src.right, src.top); - quad[2].set(src.right, src.bottom); - quad[3].set(src.left, src.bottom); - mapPoints(quad, quad, 4); - dst->setBounds(quad, 4); + Point quad[4]; + quad[0].set(src.left, src.top); + quad[1].set(src.right, src.top); + quad[2].set(src.right, src.bottom); + quad[3].set(src.left, src.bottom); + mapPoints(quad, quad, 4); + dst->setBounds(quad, 4); } float Matrix::getMinScale() const { - float results[2]; - if (getMinMaxScaleFactors(results)) { - return results[0]; - } - return -1.0f; + float results[2]; + if (getMinMaxScaleFactors(results)) { + return results[0]; + } + return -1.0f; } float Matrix::getMaxScale() const { - float results[2]; - if (getMinMaxScaleFactors(results)) { - return results[1]; - } - return -1.0f; + float results[2]; + if (getMinMaxScaleFactors(results)) { + return results[1]; + } + return -1.0f; } bool Matrix::getMinMaxScaleFactors(float* results) const { - float a = sdot(values[SCALE_X], values[SCALE_X], values[SKEW_Y], values[SKEW_Y]); - float b = sdot(values[SCALE_X], values[SKEW_X], values[SCALE_Y], values[SKEW_Y]); - float c = sdot(values[SKEW_X], values[SKEW_X], values[SCALE_Y], values[SCALE_Y]); - float bSqd = b * b; - if (bSqd <= FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO) { - results[0] = a; - results[1] = c; - if (results[0] > results[1]) { - using std::swap; - swap(results[0], results[1]); + float a = sdot(values[SCALE_X], values[SCALE_X], values[SKEW_Y], values[SKEW_Y]); + float b = sdot(values[SCALE_X], values[SKEW_X], values[SCALE_Y], values[SKEW_Y]); + float c = sdot(values[SKEW_X], values[SKEW_X], values[SCALE_Y], values[SCALE_Y]); + float bSqd = b * b; + if (bSqd <= FLOAT_NEARLY_ZERO * FLOAT_NEARLY_ZERO) { + results[0] = a; + results[1] = c; + if (results[0] > results[1]) { + using std::swap; + swap(results[0], results[1]); + } + } else { + float aminusc = a - c; + float apluscdiv2 = (a + c) * 0.5f; + float x = sqrtf(aminusc * aminusc + 4 * bSqd) * 0.5f; + results[0] = apluscdiv2 - x; + results[1] = apluscdiv2 + x; + } + auto isFinite = (results[0] * 0 == 0); + if (!isFinite) { + return false; + } + if (results[0] < 0) { + results[0] = 0; } - } else { - float aminusc = a - c; - float apluscdiv2 = (a + c) * 0.5f; - float x = sqrtf(aminusc * aminusc + 4 * bSqd) * 0.5f; - results[0] = apluscdiv2 - x; - results[1] = apluscdiv2 + x; - } - auto isFinite = (results[0] * 0 == 0); - if (!isFinite) { - return false; - } - if (results[0] < 0) { - results[0] = 0; - } - results[0] = sqrtf(results[0]); - isFinite = (results[1] * 0 == 0); - if (!isFinite) { - return false; - } - if (results[1] < 0) { - results[1] = 0; - } - results[1] = sqrtf(results[1]); - return true; + results[0] = sqrtf(results[0]); + isFinite = (results[1] * 0 == 0); + if (!isFinite) { + return false; + } + if (results[1] < 0) { + results[1] = 0; + } + results[1] = sqrtf(results[1]); + return true; } bool Matrix::isFinite() const { - return FloatsAreFinite(values, 9); + return FloatsAreFinite(values, 9); } const Matrix& Matrix::I() { - static const Matrix identity = Matrix::MakeAll(1, 0, 0, 0, 1, 0, 0, 0, 1); - return identity; + static const Matrix identity = Matrix::MakeAll(1, 0, 0, 0, 1, 0, 0, 0, 1); + return identity; } const Matrix& Matrix::Invalid() { - static const Matrix invalid = Matrix::MakeAll(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, - FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX); - return invalid; + static const Matrix invalid = Matrix::MakeAll(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, + FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX); + return invalid; } } // namespace pag \ No newline at end of file diff --git a/src/base/PathData.cpp b/src/base/PathData.cpp index deee7b7192..808611fcb3 100644 --- a/src/base/PathData.cpp +++ b/src/base/PathData.cpp @@ -23,147 +23,147 @@ namespace pag { void PathData::moveTo(float x, float y) { - verbs.push_back(PathDataVerb::MoveTo); - points.push_back({x, y}); - lastMoveTo.x = x; - lastMoveTo.y = y; + verbs.push_back(PathDataVerb::MoveTo); + points.push_back({x, y}); + lastMoveTo.x = x; + lastMoveTo.y = y; } void PathData::lineTo(float x, float y) { - if (verbs.empty()) { - moveTo(0, 0); - } - verbs.push_back(PathDataVerb::LineTo); - points.push_back({x, y}); + if (verbs.empty()) { + moveTo(0, 0); + } + verbs.push_back(PathDataVerb::LineTo); + points.push_back({x, y}); } void PathData::cubicTo(float controlX1, float controlY1, float controlX2, float controlY2, float x, float y) { - if (verbs.empty()) { - moveTo(0, 0); - } - verbs.push_back(PathDataVerb::CurveTo); - points.push_back({controlX1, controlY1}); - points.push_back({controlX2, controlY2}); - points.push_back({x, y}); + if (verbs.empty()) { + moveTo(0, 0); + } + verbs.push_back(PathDataVerb::CurveTo); + points.push_back({controlX1, controlY1}); + points.push_back({controlX2, controlY2}); + points.push_back({x, y}); } void PathData::close() { - if (verbs.empty()) { - return; - } - auto lastVerb = verbs.back(); - if (lastVerb == PathDataVerb::Close) { - return; - } - auto lastPoint = points.back(); - if (lastPoint != lastMoveTo) { - lineTo(lastMoveTo.x, lastMoveTo.y); - } - verbs.push_back(PathDataVerb::Close); + if (verbs.empty()) { + return; + } + auto lastVerb = verbs.back(); + if (lastVerb == PathDataVerb::Close) { + return; + } + auto lastPoint = points.back(); + if (lastPoint != lastMoveTo) { + lineTo(lastMoveTo.x, lastMoveTo.y); + } + verbs.push_back(PathDataVerb::Close); } bool PathData::isClosed() const { - if (verbs.empty()) { - return false; - } - return verbs.back() == PathDataVerb::Close; + if (verbs.empty()) { + return false; + } + return verbs.back() == PathDataVerb::Close; } void PathData::reverse() { - if (verbs.empty()) { - return; - } - std::reverse(points.begin(), points.end()); - std::vector list; - auto size = verbs.size(); - list.reserve(size); - verbs.swap(list); - verbs.push_back(PathDataVerb::MoveTo); - bool hasClose = false; - for (auto i = size - 1; i > 0; i--) { - auto verb = list[i]; - switch (verb) { - case PathDataVerb::Close: - if (hasClose) { - verbs.push_back(PathDataVerb::Close); - } - hasClose = true; - break; - case PathDataVerb::MoveTo: - if (hasClose) { - hasClose = false; - verbs.push_back(PathDataVerb::Close); + if (verbs.empty()) { + return; + } + std::reverse(points.begin(), points.end()); + std::vector list; + auto size = verbs.size(); + list.reserve(size); + verbs.swap(list); + verbs.push_back(PathDataVerb::MoveTo); + bool hasClose = false; + for (auto i = size - 1; i > 0; i--) { + auto verb = list[i]; + switch (verb) { + case PathDataVerb::Close: + if (hasClose) { + verbs.push_back(PathDataVerb::Close); + } + hasClose = true; + break; + case PathDataVerb::MoveTo: + if (hasClose) { + hasClose = false; + verbs.push_back(PathDataVerb::Close); + } + verbs.push_back(PathDataVerb::MoveTo); + break; + default: + verbs.push_back(verb); + break; } - verbs.push_back(PathDataVerb::MoveTo); - break; - default: - verbs.push_back(verb); - break; } - } - if (hasClose) { - verbs.push_back(PathDataVerb::Close); - } + if (hasClose) { + verbs.push_back(PathDataVerb::Close); + } } void PathData::clear() { - verbs.clear(); - points.clear(); + verbs.clear(); + points.clear(); } struct CurveData { - Point control1; - Point control2; - Point end; + Point control1; + Point control2; + Point end; }; inline CurveData GetCurveData(PathDataVerb verb, const std::vector& points, int& index) { - CurveData data = {}; - if (verb == PathDataVerb::CurveTo) { - data.control1 = points[index++]; - data.control2 = points[index++]; - data.end = points[index++]; - } else { - data.control1 = points[index - 1]; - data.end = points[index++]; - data.control2 = data.end; - } - return data; + CurveData data = {}; + if (verb == PathDataVerb::CurveTo) { + data.control1 = points[index++]; + data.control2 = points[index++]; + data.end = points[index++]; + } else { + data.control1 = points[index - 1]; + data.end = points[index++]; + data.control2 = data.end; + } + return data; } void PathData::interpolate(const PathData& path, PathData* result, float t) { - if (verbs.empty() || path.verbs.empty()) { - return; - } - auto& pointsA = points; - auto& verbsA = verbs; - auto& pointsB = path.points; - auto& verbsB = path.verbs; - int indexA = 0; - int indexB = 0; - auto size = verbsA.size(); - for (size_t i = 0; i < size; i++) { - auto verbA = verbsA[i]; - auto verbB = verbsB[i]; - if (verbA == verbB) { - result->verbs.push_back(verbA); - if (verbA == PathDataVerb::Close) { - continue; - } - auto count = verbA == PathDataVerb::CurveTo ? 3 : 1; - while (count-- > 0) { - result->points.push_back(Interpolate(pointsA[indexA++], pointsB[indexB++], t)); - } - } else { - auto dataA = GetCurveData(verbA, pointsA, indexA); - auto dataB = GetCurveData(verbB, pointsB, indexB); - result->verbs.push_back(PathDataVerb::CurveTo); - result->points.push_back(Interpolate(dataA.control1, dataB.control1, t)); - result->points.push_back(Interpolate(dataA.control2, dataB.control2, t)); - result->points.push_back(Interpolate(dataA.end, dataB.end, t)); + if (verbs.empty() || path.verbs.empty()) { + return; + } + auto& pointsA = points; + auto& verbsA = verbs; + auto& pointsB = path.points; + auto& verbsB = path.verbs; + int indexA = 0; + int indexB = 0; + auto size = verbsA.size(); + for (size_t i = 0; i < size; i++) { + auto verbA = verbsA[i]; + auto verbB = verbsB[i]; + if (verbA == verbB) { + result->verbs.push_back(verbA); + if (verbA == PathDataVerb::Close) { + continue; + } + auto count = verbA == PathDataVerb::CurveTo ? 3 : 1; + while (count-- > 0) { + result->points.push_back(Interpolate(pointsA[indexA++], pointsB[indexB++], t)); + } + } else { + auto dataA = GetCurveData(verbA, pointsA, indexA); + auto dataB = GetCurveData(verbB, pointsB, indexB); + result->verbs.push_back(PathDataVerb::CurveTo); + result->points.push_back(Interpolate(dataA.control1, dataB.control1, t)); + result->points.push_back(Interpolate(dataA.control2, dataB.control2, t)); + result->points.push_back(Interpolate(dataA.end, dataB.end, t)); + } } - } } } // namespace pag diff --git a/src/base/PreComposeLayer.cpp b/src/base/PreComposeLayer.cpp index 3d95460b11..8fd8b47808 100644 --- a/src/base/PreComposeLayer.cpp +++ b/src/base/PreComposeLayer.cpp @@ -21,72 +21,72 @@ namespace pag { std::unique_ptr PreComposeLayer::Wrap(pag::Composition* composition) { - auto layer = new PreComposeLayer(); - layer->duration = composition->duration; - layer->transform = Transform2D::MakeDefault(); - layer->composition = composition; - return std::unique_ptr(layer); + auto layer = new PreComposeLayer(); + layer->duration = composition->duration; + layer->transform = Transform2D::MakeDefault(); + layer->composition = composition; + return std::unique_ptr(layer); } void PreComposeLayer::excludeVaryingRanges(std::vector* timeRanges) { - Layer::excludeVaryingRanges(timeRanges); - if (timeRanges->empty()) { - return; - } - auto ranges = getContentStaticTimeRanges(); - TimeRange startRange = {0, startTime - 1}; - if (startRange.start < startRange.end) { - ranges.insert(ranges.begin(), startRange); - } - auto endTime = timeRanges->back().end; - TimeRange endRange = {startTime + duration, endTime}; - if (endRange.start < endRange.end) { - ranges.push_back(endRange); - } - MergeTimeRanges(timeRanges, &ranges); + Layer::excludeVaryingRanges(timeRanges); + if (timeRanges->empty()) { + return; + } + auto ranges = getContentStaticTimeRanges(); + TimeRange startRange = {0, startTime - 1}; + if (startRange.start < startRange.end) { + ranges.insert(ranges.begin(), startRange); + } + auto endTime = timeRanges->back().end; + TimeRange endRange = {startTime + duration, endTime}; + if (endRange.start < endRange.end) { + ranges.push_back(endRange); + } + MergeTimeRanges(timeRanges, &ranges); } std::vector PreComposeLayer::getContentStaticTimeRanges() const { - auto ranges = composition->staticTimeRanges; - float timeScale = 1; - if (containingComposition) { - timeScale = containingComposition->frameRate / composition->frameRate; - } - for (auto i = static_cast(ranges.size() - 1); i >= 0; i--) { - auto& range = ranges[i]; - range.start = static_cast(roundf(range.start * timeScale)); - range.end = static_cast(roundf(range.end * timeScale)); - range.start += compositionStartTime; - range.end += compositionStartTime; - if (range.end <= startTime || range.start >= startTime + duration - 1) { - ranges.erase(ranges.begin() + i); - } else { - if (range.start < startTime) { - range.start = startTime; - } - if (range.end > startTime + duration - 1) { - range.end = startTime + duration - 1; - } - if (range.start == range.end) { - ranges.erase(ranges.begin() + i); - } + auto ranges = composition->staticTimeRanges; + float timeScale = 1; + if (containingComposition) { + timeScale = containingComposition->frameRate / composition->frameRate; } - } - return ranges; + for (auto i = static_cast(ranges.size() - 1); i >= 0; i--) { + auto& range = ranges[i]; + range.start = static_cast(roundf(range.start * timeScale)); + range.end = static_cast(roundf(range.end * timeScale)); + range.start += compositionStartTime; + range.end += compositionStartTime; + if (range.end <= startTime || range.start >= startTime + duration - 1) { + ranges.erase(ranges.begin() + i); + } else { + if (range.start < startTime) { + range.start = startTime; + } + if (range.end > startTime + duration - 1) { + range.end = startTime + duration - 1; + } + if (range.start == range.end) { + ranges.erase(ranges.begin() + i); + } + } + } + return ranges; } Frame PreComposeLayer::getCompositionFrame(Frame layerFrame) { - auto timeScale = - containingComposition ? (composition->frameRate / containingComposition->frameRate) : 1.0f; - return static_cast( - roundf(static_cast(layerFrame - compositionStartTime) * timeScale)); + auto timeScale = + containingComposition ? (composition->frameRate / containingComposition->frameRate) : 1.0f; + return static_cast( + roundf(static_cast(layerFrame - compositionStartTime) * timeScale)); } bool PreComposeLayer::verify() const { - if (!Layer::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(composition != nullptr); + if (!Layer::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(composition != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/Rect.cpp b/src/base/Rect.cpp index d85af84c6b..a96f170142 100644 --- a/src/base/Rect.cpp +++ b/src/base/Rect.cpp @@ -21,45 +21,45 @@ namespace pag { void Rect::scale(float scaleX, float scaleY) { - left *= scaleX; - right *= scaleY; - top *= scaleX; - bottom *= scaleY; + left *= scaleX; + right *= scaleY; + top *= scaleX; + bottom *= scaleY; } bool Rect::setBounds(const Point pts[], int count) { - if (count <= 0) { - this->setEmpty(); - return true; - } - float minX, maxX; - float minY, maxY; - minX = maxX = pts[0].x; - minY = maxY = pts[0].y; - - for (int i = 1; i < count; i++) { - auto x = pts[i].x; - auto y = pts[i].y; - auto isFinite = ((x + y) * 0 == 0); - if (!isFinite) { - setEmpty(); - return false; - } - if (x < minX) { - minX = x; + if (count <= 0) { + this->setEmpty(); + return true; } - if (x > maxX) { - maxX = x; - } - if (y < minY) { - minY = y; - } - if (y > maxY) { - maxY = y; + float minX, maxX; + float minY, maxY; + minX = maxX = pts[0].x; + minY = maxY = pts[0].y; + + for (int i = 1; i < count; i++) { + auto x = pts[i].x; + auto y = pts[i].y; + auto isFinite = ((x + y) * 0 == 0); + if (!isFinite) { + setEmpty(); + return false; + } + if (x < minX) { + minX = x; + } + if (x > maxX) { + maxX = x; + } + if (y < minY) { + minY = y; + } + if (y > maxY) { + maxY = y; + } } - } - setLTRB(minX, minY, maxX, maxY); - return true; + setLTRB(minX, minY, maxX, maxY); + return true; } #define CHECK_INTERSECT(al, at, ar, ab, bl, bt, br, bb) \ @@ -75,30 +75,30 @@ bool Rect::setBounds(const Point pts[], int count) { // do the !(opposite) check so we return false if either arg is NaN bool Rect::intersect(float l, float t, float r, float b) { - CHECK_INTERSECT(l, t, r, b, left, top, right, bottom); - this->setLTRB(L, T, R, B); - return true; + CHECK_INTERSECT(l, t, r, b, left, top, right, bottom); + this->setLTRB(L, T, R, B); + return true; } bool Rect::intersect(const Rect& a, const Rect& b) { - CHECK_INTERSECT(a.left, a.top, a.right, a.bottom, b.left, b.top, b.right, b.bottom); - this->setLTRB(L, T, R, B); - return true; + CHECK_INTERSECT(a.left, a.top, a.right, a.bottom, b.left, b.top, b.right, b.bottom); + this->setLTRB(L, T, R, B); + return true; } void Rect::join(float l, float t, float r, float b) { - // do nothing if the params are empty - if (l >= r || t >= b) { - return; - } - // if we are empty, just assign - if (left >= right || top >= bottom) { - this->setLTRB(l, t, r, b); - } else { - left = left < l ? left : l; - top = top < t ? top : t; - right = right > r ? right : r; - bottom = bottom > b ? bottom : b; - } + // do nothing if the params are empty + if (l >= r || t >= b) { + return; + } + // if we are empty, just assign + if (left >= right || top >= bottom) { + this->setLTRB(l, t, r, b); + } else { + left = left < l ? left : l; + top = top < t ? top : t; + right = right > r ? right : r; + bottom = bottom > b ? bottom : b; + } } } // namespace pag \ No newline at end of file diff --git a/src/base/Sequence.cpp b/src/base/Sequence.cpp index 60c335c2e5..946ea3cb0c 100644 --- a/src/base/Sequence.cpp +++ b/src/base/Sequence.cpp @@ -21,32 +21,32 @@ namespace pag { Sequence* Sequence::Get(Composition* composition) { - // Currently, we use the last one for best rendering quality, ignore all others. - if (composition != nullptr) { - switch (composition->type()) { - case CompositionType::Video: - return static_cast(composition)->sequences.back(); - case CompositionType::Bitmap: - return static_cast(composition)->sequences.back(); - default: - break; + // Currently, we use the last one for best rendering quality, ignore all others. + if (composition != nullptr) { + switch (composition->type()) { + case CompositionType::Video: + return static_cast(composition)->sequences.back(); + case CompositionType::Bitmap: + return static_cast(composition)->sequences.back(); + default: + break; + } } - } - return nullptr; + return nullptr; } bool Sequence::verify() const { - VerifyAndReturn(composition != nullptr && width > 0 && height > 0 && frameRate > 0); + VerifyAndReturn(composition != nullptr && width > 0 && height > 0 && frameRate > 0); } Frame Sequence::toSequenceFrame(Frame compositionFrame) { - auto sequenceFrame = - ConvertFrameByStaticTimeRanges(composition->staticTimeRanges, compositionFrame); - double timeScale = frameRate / composition->frameRate; - sequenceFrame = static_cast(round(sequenceFrame * timeScale)); - if (sequenceFrame >= duration()) { - sequenceFrame = static_cast(duration()) - 1; - } - return sequenceFrame; + auto sequenceFrame = + ConvertFrameByStaticTimeRanges(composition->staticTimeRanges, compositionFrame); + double timeScale = frameRate / composition->frameRate; + sequenceFrame = static_cast(round(sequenceFrame * timeScale)); + if (sequenceFrame >= duration()) { + sequenceFrame = static_cast(duration()) - 1; + } + return sequenceFrame; } } // namespace pag \ No newline at end of file diff --git a/src/base/ShapeLayer.cpp b/src/base/ShapeLayer.cpp index 6d03697d91..245ee17359 100644 --- a/src/base/ShapeLayer.cpp +++ b/src/base/ShapeLayer.cpp @@ -22,30 +22,30 @@ namespace pag { ShapeLayer::~ShapeLayer() { - for (auto& element : contents) { - delete element; - } + for (auto& element : contents) { + delete element; + } } void ShapeLayer::excludeVaryingRanges(std::vector* timeRanges) { - Layer::excludeVaryingRanges(timeRanges); - for (auto& element : contents) { - element->excludeVaryingRanges(timeRanges); - } + Layer::excludeVaryingRanges(timeRanges); + for (auto& element : contents) { + element->excludeVaryingRanges(timeRanges); + } } bool ShapeLayer::verify() const { - if (!Layer::verify()) { - VerifyFailed(); - return false; - } - for (auto& element : contents) { - if (element == nullptr || !element->verify()) { - VerifyFailed(); - return false; + if (!Layer::verify()) { + VerifyFailed(); + return false; + } + for (auto& element : contents) { + if (element == nullptr || !element->verify()) { + VerifyFailed(); + return false; + } } - } - return true; + return true; } } // namespace pag diff --git a/src/base/SolidLayer.cpp b/src/base/SolidLayer.cpp index 33fa26d35f..692b836c69 100644 --- a/src/base/SolidLayer.cpp +++ b/src/base/SolidLayer.cpp @@ -21,10 +21,10 @@ namespace pag { bool SolidLayer::verify() const { - if (!Layer::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(width > 0 && height > 0); + if (!Layer::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(width > 0 && height > 0); } } // namespace pag \ No newline at end of file diff --git a/src/base/TextLayer.cpp b/src/base/TextLayer.cpp index 3af10d8ddf..ae5d6a38ad 100644 --- a/src/base/TextLayer.cpp +++ b/src/base/TextLayer.cpp @@ -22,59 +22,59 @@ namespace pag { TextLayer::~TextLayer() { - delete sourceText; - delete pathOption; - delete moreOption; - for (auto& animator : animators) { - delete animator; - } + delete sourceText; + delete pathOption; + delete moreOption; + for (auto& animator : animators) { + delete animator; + } } TextDocumentHandle TextLayer::getTextDocument() { - if (sourceText == nullptr) { - return nullptr; - } - if (sourceText->animatable()) { - auto keyframes = - reinterpret_cast*>(sourceText)->keyframes; - return keyframes[0]->startValue; - } - return sourceText->getValueAt(0); + if (sourceText == nullptr) { + return nullptr; + } + if (sourceText->animatable()) { + auto keyframes = + reinterpret_cast*>(sourceText)->keyframes; + return keyframes[0]->startValue; + } + return sourceText->getValueAt(0); } void TextLayer::excludeVaryingRanges(std::vector* timeRanges) { - Layer::excludeVaryingRanges(timeRanges); - sourceText->excludeVaryingRanges(timeRanges); - if (pathOption) { - pathOption->excludeVaryingRanges(timeRanges); - } - if (moreOption) { - moreOption->excludeVaryingRanges(timeRanges); - } - for (auto& animator : animators) { - animator->excludeVaryingRanges(timeRanges); - } + Layer::excludeVaryingRanges(timeRanges); + sourceText->excludeVaryingRanges(timeRanges); + if (pathOption) { + pathOption->excludeVaryingRanges(timeRanges); + } + if (moreOption) { + moreOption->excludeVaryingRanges(timeRanges); + } + for (auto& animator : animators) { + animator->excludeVaryingRanges(timeRanges); + } } bool TextLayer::verify() const { - if (!Layer::verify()) { - VerifyFailed(); - return false; - } - if (sourceText == nullptr) { - VerifyFailed(); - return false; - } - if (pathOption != nullptr && !pathOption->verify()) { - VerifyFailed(); - return false; - } - for (auto& animator : animators) { - if (animator == nullptr || !animator->verify()) { - VerifyFailed(); - return false; + if (!Layer::verify()) { + VerifyFailed(); + return false; + } + if (sourceText == nullptr) { + VerifyFailed(); + return false; + } + if (pathOption != nullptr && !pathOption->verify()) { + VerifyFailed(); + return false; + } + for (auto& animator : animators) { + if (animator == nullptr || !animator->verify()) { + VerifyFailed(); + return false; + } } - } - VerifyAndReturn(moreOption == nullptr || moreOption->verify()); + VerifyAndReturn(moreOption == nullptr || moreOption->verify()); } } // namespace pag diff --git a/src/base/TimeRange.cpp b/src/base/TimeRange.cpp index c06bd7e9cf..f6afbeca03 100644 --- a/src/base/TimeRange.cpp +++ b/src/base/TimeRange.cpp @@ -22,150 +22,150 @@ namespace pag { static void TargetInsideTimeRange(std::vector* timeRanges, int i, Frame startTime, Frame endTime) { - auto& timeRange = (*timeRanges)[i]; - TimeRange range = {endTime + 1, timeRange.end}; - timeRange.end = startTime - 1; - if (range.end > range.start) { - timeRanges->insert(timeRanges->begin() + i + 1, range); - } - if (timeRange.end <= timeRange.start) { - timeRanges->erase(timeRanges->begin() + i); - } + auto& timeRange = (*timeRanges)[i]; + TimeRange range = {endTime + 1, timeRange.end}; + timeRange.end = startTime - 1; + if (range.end > range.start) { + timeRanges->insert(timeRanges->begin() + i + 1, range); + } + if (timeRange.end <= timeRange.start) { + timeRanges->erase(timeRanges->begin() + i); + } } static void TargetIntersectTimeRange(std::vector* timeRanges, int i, Frame startTime, Frame endTime) { - auto& timeRange = (*timeRanges)[i]; - if (timeRange.start < startTime) { - timeRange.end = startTime - 1; - } else { - timeRange.start = endTime + 1; - } - if (timeRange.end <= timeRange.start) { - timeRanges->erase(timeRanges->begin() + i); - } + auto& timeRange = (*timeRanges)[i]; + if (timeRange.start < startTime) { + timeRange.end = startTime - 1; + } else { + timeRange.start = endTime + 1; + } + if (timeRange.end <= timeRange.start) { + timeRanges->erase(timeRanges->begin() + i); + } } void SubtractFromTimeRanges(std::vector* timeRanges, Frame startTime, Frame endTime) { - if (endTime < startTime) { - SplitTimeRangesAt(timeRanges, startTime); - return; - } - auto size = static_cast(timeRanges->size()); - for (int i = size - 1; i >= 0; i--) { - auto& timeRange = (*timeRanges)[i]; - if (timeRange.end < startTime || timeRange.start > endTime) { - // target outside timeRange - continue; - } - if (timeRange.start < startTime && timeRange.end > endTime) { - // target inside timeRange - TargetInsideTimeRange(timeRanges, i, startTime, endTime); - break; + if (endTime < startTime) { + SplitTimeRangesAt(timeRanges, startTime); + return; } - if (timeRange.start >= startTime && timeRange.end <= endTime) { - // target contain timeRange - timeRanges->erase(timeRanges->begin() + i); - } else { - // target intersect timeRange - TargetIntersectTimeRange(timeRanges, i, startTime, endTime); + auto size = static_cast(timeRanges->size()); + for (int i = size - 1; i >= 0; i--) { + auto& timeRange = (*timeRanges)[i]; + if (timeRange.end < startTime || timeRange.start > endTime) { + // target outside timeRange + continue; + } + if (timeRange.start < startTime && timeRange.end > endTime) { + // target inside timeRange + TargetInsideTimeRange(timeRanges, i, startTime, endTime); + break; + } + if (timeRange.start >= startTime && timeRange.end <= endTime) { + // target contain timeRange + timeRanges->erase(timeRanges->begin() + i); + } else { + // target intersect timeRange + TargetIntersectTimeRange(timeRanges, i, startTime, endTime); + } } - } } void SplitTimeRangesAt(std::vector* timeRanges, Frame startTime) { - auto size = static_cast(timeRanges->size()); - for (int i = size - 1; i >= 0; i--) { - auto timeRange = (*timeRanges)[i]; - if (timeRange.start == startTime || timeRange.end < startTime) { - break; - } - if (timeRange.start < startTime && timeRange.end >= startTime) { - TimeRange range = {startTime, timeRange.end}; - (*timeRanges)[i].end = timeRange.end = startTime - 1; - if (range.end > range.start) { - timeRanges->insert(timeRanges->begin() + i + 1, range); - } - if (timeRange.end <= timeRange.start) { - timeRanges->erase(timeRanges->begin() + i); - } - break; + auto size = static_cast(timeRanges->size()); + for (int i = size - 1; i >= 0; i--) { + auto timeRange = (*timeRanges)[i]; + if (timeRange.start == startTime || timeRange.end < startTime) { + break; + } + if (timeRange.start < startTime && timeRange.end >= startTime) { + TimeRange range = {startTime, timeRange.end}; + (*timeRanges)[i].end = timeRange.end = startTime - 1; + if (range.end > range.start) { + timeRanges->insert(timeRanges->begin() + i + 1, range); + } + if (timeRange.end <= timeRange.start) { + timeRanges->erase(timeRanges->begin() + i); + } + break; + } } - } } void MergeTimeRanges(std::vector* timeRanges, const std::vector* otherRanges) { - std::vector intersections; - auto mergeFunc = [otherRanges, &intersections](TimeRange& timeRange) { - for (auto& range : *otherRanges) { - if (range.end < timeRange.start) { - continue; - } - if (range.start > timeRange.end) { - break; - } - if (range.start <= timeRange.start && range.end >= timeRange.end) { - intersections.push_back(timeRange); - break; - } - if (range.start >= timeRange.start && range.end <= timeRange.end) { - intersections.push_back(range); - continue; - } - if (range.start < timeRange.start) { - TimeRange newRange = {timeRange.start, range.end}; - intersections.push_back(newRange); - continue; - } - if (range.end > timeRange.end) { - TimeRange newRange = {range.start, timeRange.end}; - intersections.push_back(newRange); - } - } - }; - std::for_each(timeRanges->begin(), timeRanges->end(), mergeFunc); - *timeRanges = intersections; + std::vector intersections; + auto mergeFunc = [otherRanges, &intersections](TimeRange& timeRange) { + for (auto& range : *otherRanges) { + if (range.end < timeRange.start) { + continue; + } + if (range.start > timeRange.end) { + break; + } + if (range.start <= timeRange.start && range.end >= timeRange.end) { + intersections.push_back(timeRange); + break; + } + if (range.start >= timeRange.start && range.end <= timeRange.end) { + intersections.push_back(range); + continue; + } + if (range.start < timeRange.start) { + TimeRange newRange = {timeRange.start, range.end}; + intersections.push_back(newRange); + continue; + } + if (range.end > timeRange.end) { + TimeRange newRange = {range.start, timeRange.end}; + intersections.push_back(newRange); + } + } + }; + std::for_each(timeRanges->begin(), timeRanges->end(), mergeFunc); + *timeRanges = intersections; } std::vector OffsetTimeRanges(const std::vector& timeRanges, Frame offsetTime) { - std::vector newTimeRanges = {}; - for (auto timeRange : timeRanges) { - timeRange.start += offsetTime; - timeRange.end += offsetTime; - newTimeRanges.push_back(timeRange); - } - return newTimeRanges; + std::vector newTimeRanges = {}; + for (auto timeRange : timeRanges) { + timeRange.start += offsetTime; + timeRange.end += offsetTime; + newTimeRanges.push_back(timeRange); + } + return newTimeRanges; } bool HasVaryingTimeRange(const std::vector* staticTimeRanges, Frame startTime, Frame duration) { - if (staticTimeRanges->size() == 1) { - auto& range = (*staticTimeRanges)[0]; - if (range.start == startTime && range.end == startTime + duration - 1) { - return false; + if (staticTimeRanges->size() == 1) { + auto& range = (*staticTimeRanges)[0]; + if (range.start == startTime && range.end == startTime + duration - 1) { + return false; + } } - } - return true; + return true; } int FindTimeRangeAt(const std::vector& timeRanges, Frame position, int start, int end) { - if (start > end) { - return -1; - } - auto index = static_cast((start + end) * 0.5); - auto& timeRange = timeRanges[index]; - if (timeRange.start > position) { - return FindTimeRangeAt(timeRanges, position, start, index - 1); - } else if (timeRange.end < position) { - return FindTimeRangeAt(timeRanges, position, index + 1, end); - } else { - return index; - } + if (start > end) { + return -1; + } + auto index = static_cast((start + end) * 0.5); + auto& timeRange = timeRanges[index]; + if (timeRange.start > position) { + return FindTimeRangeAt(timeRanges, position, start, index - 1); + } else if (timeRange.end < position) { + return FindTimeRangeAt(timeRanges, position, index + 1, end); + } else { + return index; + } } Frame ConvertFrameByStaticTimeRanges(const std::vector& timeRanges, Frame frame) { - auto index = FindTimeRangeAt(timeRanges, frame, 0, static_cast(timeRanges.size() - 1)); - return index != -1 ? timeRanges[index].start : frame; + auto index = FindTimeRangeAt(timeRanges, frame, 0, static_cast(timeRanges.size() - 1)); + return index != -1 ? timeRanges[index].start : frame; } } // namespace pag diff --git a/src/base/Transform2D.cpp b/src/base/Transform2D.cpp index 646c14bf96..ee8360a272 100644 --- a/src/base/Transform2D.cpp +++ b/src/base/Transform2D.cpp @@ -21,45 +21,45 @@ namespace pag { Transform2D* Transform2D::MakeDefault() { - auto transform = new Transform2D(); - transform->anchorPoint = new Property(); - transform->anchorPoint->value = Point::Zero(); - transform->position = new Property(); - transform->position->value = Point::Zero(); - transform->scale = new Property(); - transform->scale->value = Point::Make(1, 1); - transform->rotation = new Property(); - transform->rotation->value = 0.0f; - transform->opacity = new Property(); - transform->opacity->value = Opaque; - return transform; + auto transform = new Transform2D(); + transform->anchorPoint = new Property(); + transform->anchorPoint->value = Point::Zero(); + transform->position = new Property(); + transform->position->value = Point::Zero(); + transform->scale = new Property(); + transform->scale->value = Point::Make(1, 1); + transform->rotation = new Property(); + transform->rotation->value = 0.0f; + transform->opacity = new Property(); + transform->opacity->value = Opaque; + return transform; } Transform2D::~Transform2D() { - delete anchorPoint; - delete position; - delete xPosition; - delete yPosition; - delete scale; - delete rotation; - delete opacity; + delete anchorPoint; + delete position; + delete xPosition; + delete yPosition; + delete scale; + delete rotation; + delete opacity; } void Transform2D::excludeVaryingRanges(std::vector* timeRanges) const { - anchorPoint->excludeVaryingRanges(timeRanges); - if (position != nullptr) { - position->excludeVaryingRanges(timeRanges); - } else { - xPosition->excludeVaryingRanges(timeRanges); - yPosition->excludeVaryingRanges(timeRanges); - } - scale->excludeVaryingRanges(timeRanges); - rotation->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); + anchorPoint->excludeVaryingRanges(timeRanges); + if (position != nullptr) { + position->excludeVaryingRanges(timeRanges); + } else { + xPosition->excludeVaryingRanges(timeRanges); + yPosition->excludeVaryingRanges(timeRanges); + } + scale->excludeVaryingRanges(timeRanges); + rotation->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); } bool Transform2D::verify() const { - VerifyAndReturn(anchorPoint != nullptr && - (position != nullptr || (xPosition != nullptr && yPosition != nullptr)) && - scale != nullptr && rotation != nullptr && opacity != nullptr); + VerifyAndReturn(anchorPoint != nullptr && + (position != nullptr || (xPosition != nullptr && yPosition != nullptr)) && + scale != nullptr && rotation != nullptr && opacity != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/VectorComposition.cpp b/src/base/VectorComposition.cpp index 0806a99d71..397d31ec57 100644 --- a/src/base/VectorComposition.cpp +++ b/src/base/VectorComposition.cpp @@ -22,67 +22,67 @@ namespace pag { VectorComposition::~VectorComposition() { - for (auto& layer : layers) { - delete layer; - } + for (auto& layer : layers) { + delete layer; + } } CompositionType VectorComposition::type() const { - return CompositionType::Vector; + return CompositionType::Vector; } void VectorComposition::updateStaticTimeRanges() { - staticTimeRanges = {}; - if (duration <= 1) { - return; - } - TimeRange range = {0, duration - 1}; - staticTimeRanges.push_back(range); - for (auto layer : layers) { - if (staticTimeRanges.empty()) { - break; + staticTimeRanges = {}; + if (duration <= 1) { + return; } - if (layer->type() == LayerType::PreCompose) { - auto composition = static_cast(layer)->composition; - if (!composition->staticTimeRangeUpdated) { - composition->updateStaticTimeRanges(); - composition->staticTimeRangeUpdated = true; - } + TimeRange range = {0, duration - 1}; + staticTimeRanges.push_back(range); + for (auto layer : layers) { + if (staticTimeRanges.empty()) { + break; + } + if (layer->type() == LayerType::PreCompose) { + auto composition = static_cast(layer)->composition; + if (!composition->staticTimeRangeUpdated) { + composition->updateStaticTimeRanges(); + composition->staticTimeRangeUpdated = true; + } + } + layer->excludeVaryingRanges(&staticTimeRanges); + SplitTimeRangesAt(&staticTimeRanges, layer->startTime); + SplitTimeRangesAt(&staticTimeRanges, layer->startTime + layer->duration); } - layer->excludeVaryingRanges(&staticTimeRanges); - SplitTimeRangesAt(&staticTimeRanges, layer->startTime); - SplitTimeRangesAt(&staticTimeRanges, layer->startTime + layer->duration); - } } bool VectorComposition::hasImageContent() const { - for (auto& layer : layers) { - switch (layer->type()) { - case LayerType::PreCompose: - if (static_cast(layer)->composition->hasImageContent()) { - return true; + for (auto& layer : layers) { + switch (layer->type()) { + case LayerType::PreCompose: + if (static_cast(layer)->composition->hasImageContent()) { + return true; + } + break; + case LayerType::Image: + return true; + default: + break; } - break; - case LayerType::Image: - return true; - default: - break; } - } - return false; + return false; } bool VectorComposition::verify() const { - if (!Composition::verify()) { - VerifyFailed(); - return false; - } - for (auto layer : layers) { - if (layer == nullptr || !layer->verify()) { - VerifyFailed(); - return false; + if (!Composition::verify()) { + VerifyFailed(); + return false; + } + for (auto layer : layers) { + if (layer == nullptr || !layer->verify()) { + VerifyFailed(); + return false; + } } - } - return true; + return true; } } // namespace pag \ No newline at end of file diff --git a/src/base/VideoComposition.cpp b/src/base/VideoComposition.cpp index a2f30e3e8f..9d82b64fac 100644 --- a/src/base/VideoComposition.cpp +++ b/src/base/VideoComposition.cpp @@ -21,56 +21,56 @@ namespace pag { VideoComposition::~VideoComposition() { - for (auto sequence : sequences) { - delete sequence; - } + for (auto sequence : sequences) { + delete sequence; + } } CompositionType VideoComposition::type() const { - return CompositionType::Video; + return CompositionType::Video; } void VideoComposition::updateStaticTimeRanges() { - staticTimeRanges = {}; - if (duration <= 1) { - return; - } - if (!sequences.empty()) { - auto sequence = sequences[0]; - for (size_t i = 1; i < sequences.size(); i++) { - auto item = sequences[i]; - if (item->frameRate > sequence->frameRate) { - sequence = item; - } + staticTimeRanges = {}; + if (duration <= 1) { + return; } - float timeScale = frameRate / sequence->frameRate; - for (auto timeRange : sequence->staticTimeRanges) { - timeRange.start = static_cast(roundf(timeRange.start * timeScale)); - timeRange.end = static_cast(roundf(timeRange.end * timeScale)); - staticTimeRanges.push_back(timeRange); + if (!sequences.empty()) { + auto sequence = sequences[0]; + for (size_t i = 1; i < sequences.size(); i++) { + auto item = sequences[i]; + if (item->frameRate > sequence->frameRate) { + sequence = item; + } + } + float timeScale = frameRate / sequence->frameRate; + for (auto timeRange : sequence->staticTimeRanges) { + timeRange.start = static_cast(roundf(timeRange.start * timeScale)); + timeRange.end = static_cast(roundf(timeRange.end * timeScale)); + staticTimeRanges.push_back(timeRange); + } + } else { + TimeRange range = {0, duration - 1}; + staticTimeRanges.push_back(range); } - } else { - TimeRange range = {0, duration - 1}; - staticTimeRanges.push_back(range); - } } bool VideoComposition::hasImageContent() const { - return true; + return true; } bool VideoComposition::verify() const { - if (!Composition::verify() || sequences.empty()) { - VerifyFailed(); - return false; - } - auto sequenceValid = [](VideoSequence* sequence) { - return sequence != nullptr && sequence->verify(); - }; - if (!std::all_of(sequences.begin(), sequences.end(), sequenceValid)) { - VerifyFailed(); - return false; - } - return true; + if (!Composition::verify() || sequences.empty()) { + VerifyFailed(); + return false; + } + auto sequenceValid = [](VideoSequence* sequence) { + return sequence != nullptr && sequence->verify(); + }; + if (!std::all_of(sequences.begin(), sequences.end(), sequenceValid)) { + VerifyFailed(); + return false; + } + return true; } } // namespace pag diff --git a/src/base/VideoSequence.cpp b/src/base/VideoSequence.cpp index 7e5da162f4..1f99eee389 100644 --- a/src/base/VideoSequence.cpp +++ b/src/base/VideoSequence.cpp @@ -21,36 +21,38 @@ namespace pag { VideoFrame::~VideoFrame() { - delete fileBytes; + delete fileBytes; } VideoSequence::~VideoSequence() { - for (auto frame : frames) { - delete frame; - } + for (auto frame : frames) { + delete frame; + } - for (auto header : headers) { - delete header; - } + for (auto header : headers) { + delete header; + } } bool VideoSequence::verify() const { - if (!Sequence::verify() || frames.empty()) { - VerifyFailed(); - return false; - } - auto frameNotNull = [](VideoFrame* frame) { - return frame != nullptr && frame->fileBytes != nullptr; - }; - if (!std::all_of(frames.begin(), frames.end(), frameNotNull)) { - VerifyFailed(); - return false; - } - auto headerNotNull = [](ByteData* header) { return header != nullptr; }; - if (!std::all_of(headers.begin(), headers.end(), headerNotNull)) { - VerifyFailed(); - return false; - } - return true; + if (!Sequence::verify() || frames.empty()) { + VerifyFailed(); + return false; + } + auto frameNotNull = [](VideoFrame* frame) { + return frame != nullptr && frame->fileBytes != nullptr; + }; + if (!std::all_of(frames.begin(), frames.end(), frameNotNull)) { + VerifyFailed(); + return false; + } + auto headerNotNull = [](ByteData* header) { + return header != nullptr; + }; + if (!std::all_of(headers.begin(), headers.end(), headerNotNull)) { + VerifyFailed(); + return false; + } + return true; } } // namespace pag diff --git a/src/base/effects/BulgeEffect.cpp b/src/base/effects/BulgeEffect.cpp index 1607cd21a1..4d70a2adc2 100644 --- a/src/base/effects/BulgeEffect.cpp +++ b/src/base/effects/BulgeEffect.cpp @@ -24,139 +24,139 @@ namespace pag { static void ConvertEllipseToPath(Path* path, float centerX, float centerY, float radiusX, float radiusY) { - auto start = -M_PI_2_F; - auto endAngle = M_PI_F + M_PI_2_F; - auto end = 0; - auto currentX = centerX + cosf(start) * radiusX; - auto currentY = centerY + sinf(start) * radiusY; - path->moveTo(currentX, currentY); - auto u = cosf(start); - auto v = sinf(start); - for (int i = 0; i < 4; i++) { - auto addAngle = end - start; - auto a = 4 * tanf(addAngle * 0.25f) / 3; - auto x1 = currentX - v * a * radiusX; - auto y1 = currentY + u * a * radiusY; - u = cosf(end); - v = sinf(end); - currentX = centerX + u * radiusX; - currentY = centerY + v * radiusY; - auto x2 = currentX + v * a * radiusX; - auto y2 = currentY - u * a * radiusY; - path->cubicTo(x1, y1, x2, y2, currentX, currentY); - if (end == endAngle) { - break; + auto start = -M_PI_2_F; + auto endAngle = M_PI_F + M_PI_2_F; + auto end = 0; + auto currentX = centerX + cosf(start) * radiusX; + auto currentY = centerY + sinf(start) * radiusY; + path->moveTo(currentX, currentY); + auto u = cosf(start); + auto v = sinf(start); + for (int i = 0; i < 4; i++) { + auto addAngle = end - start; + auto a = 4 * tanf(addAngle * 0.25f) / 3; + auto x1 = currentX - v * a * radiusX; + auto y1 = currentY + u * a * radiusY; + u = cosf(end); + v = sinf(end); + currentX = centerX + u * radiusX; + currentY = centerY + v * radiusY; + auto x2 = currentX + v * a * radiusX; + auto y2 = currentY - u * a * radiusY; + path->cubicTo(x1, y1, x2, y2, currentX, currentY); + if (end == endAngle) { + break; + } + start = end; + end = start + M_PI_2_F; + if (end > endAngle) { + end = endAngle; + } } - start = end; - end = start + M_PI_2_F; - if (end > endAngle) { - end = endAngle; - } - } - path->close(); + path->close(); } BulgeEffect::~BulgeEffect() { - delete horizontalRadius; - delete verticalRadius; - delete bulgeCenter; - delete bulgeHeight; - delete taperRadius; - delete pinning; + delete horizontalRadius; + delete verticalRadius; + delete bulgeCenter; + delete bulgeHeight; + delete taperRadius; + delete pinning; } bool BulgeEffect::visibleAt(Frame layerFrame) const { - auto horizontalRadiusValue = horizontalRadius->getValueAt(layerFrame); - auto verticalRadiusValue = verticalRadius->getValueAt(layerFrame); - auto height = bulgeHeight->getValueAt(layerFrame); - return height != 0.0f && horizontalRadiusValue != 0.0f && verticalRadiusValue != 0.0f; + auto horizontalRadiusValue = horizontalRadius->getValueAt(layerFrame); + auto verticalRadiusValue = verticalRadius->getValueAt(layerFrame); + auto height = bulgeHeight->getValueAt(layerFrame); + return height != 0.0f && horizontalRadiusValue != 0.0f && verticalRadiusValue != 0.0f; } void AdjustLeft(const Point& bulgeCenterValue, float horizontalRadiusValue, float* left) { - auto leftDiffer = - bulgeCenterValue.x > *left ? (*left - (bulgeCenterValue.x - horizontalRadiusValue)) : 0; - if (leftDiffer > 0) { - *left -= leftDiffer; - } + auto leftDiffer = + bulgeCenterValue.x > *left ? (*left - (bulgeCenterValue.x - horizontalRadiusValue)) : 0; + if (leftDiffer > 0) { + *left -= leftDiffer; + } } void AdjustRight(const Point& bulgeCenterValue, float horizontalRadiusValue, float* right) { - auto rightDiffer = - bulgeCenterValue.y < *right ? ((bulgeCenterValue.x + horizontalRadiusValue) - *right) : 0; - if (rightDiffer > 0) { - *right += rightDiffer; - } + auto rightDiffer = + bulgeCenterValue.y < *right ? ((bulgeCenterValue.x + horizontalRadiusValue) - *right) : 0; + if (rightDiffer > 0) { + *right += rightDiffer; + } } void AdjustTop(const Point& bulgeCenterValue, float verticalRadiusValue, float* top) { - auto topDiffer = - bulgeCenterValue.y > *top ? (*top - (bulgeCenterValue.y - verticalRadiusValue)) : 0; - if (topDiffer > 0) { - *top -= topDiffer; - } + auto topDiffer = + bulgeCenterValue.y > *top ? (*top - (bulgeCenterValue.y - verticalRadiusValue)) : 0; + if (topDiffer > 0) { + *top -= topDiffer; + } } void AdjustBottom(const Point& bulgeCenterValue, float verticalRadiusValue, float* bottom) { - auto bottomDiffer = - (bulgeCenterValue.y < *bottom) ? ((bulgeCenterValue.y + verticalRadiusValue) - *bottom) : 0; - if (bottomDiffer > 0) { - *bottom += bottomDiffer; - } + auto bottomDiffer = + (bulgeCenterValue.y < *bottom) ? ((bulgeCenterValue.y + verticalRadiusValue) - *bottom) : 0; + if (bottomDiffer > 0) { + *bottom += bottomDiffer; + } } void BulgeEffect::transformBounds(Rect* contentBounds, const Point&, Frame layerFrame) const { - auto horizontalRadiusValue = horizontalRadius->getValueAt(layerFrame); - auto verticalRadiusValue = verticalRadius->getValueAt(layerFrame); - auto bulgeCenterValue = bulgeCenter->getValueAt(layerFrame); - auto bulgeHeightValue = bulgeHeight->getValueAt(layerFrame); - auto pinningValue = pinning->getValueAt(layerFrame); - // 凸出特效固定开启的话,不改变尺寸。 - if (pinningValue || bulgeHeightValue == 0) { - return; - } + auto horizontalRadiusValue = horizontalRadius->getValueAt(layerFrame); + auto verticalRadiusValue = verticalRadius->getValueAt(layerFrame); + auto bulgeCenterValue = bulgeCenter->getValueAt(layerFrame); + auto bulgeHeightValue = bulgeHeight->getValueAt(layerFrame); + auto pinningValue = pinning->getValueAt(layerFrame); + // 凸出特效固定开启的话,不改变尺寸。 + if (pinningValue || bulgeHeightValue == 0) { + return; + } - auto left = contentBounds->left; - auto top = contentBounds->top; - auto right = contentBounds->right; - auto bottom = contentBounds->bottom; + auto left = contentBounds->left; + auto top = contentBounds->top; + auto right = contentBounds->right; + auto bottom = contentBounds->bottom; - Path ellipsePath = {}; - // radius 需要加 1,如果 2 者相交只有一个点时,intersectPath.isEmpty 为 true - ConvertEllipseToPath(&ellipsePath, bulgeCenterValue.x, bulgeCenterValue.y, - horizontalRadiusValue + 1, verticalRadiusValue + 1); - Path boundsPath = {}; - boundsPath.addRect(left, top, right, bottom); - auto intersectPath = ellipsePath; - intersectPath.addPath(boundsPath, PathOp::Intersect); - // 凸出效果的椭圆与内容 bounds 没有交集,不改变尺寸 - if (intersectPath.isEmpty() && !intersectPath.isInverseFillType()) { - return; - } - // 计算凸出范围 - AdjustLeft(bulgeCenterValue, horizontalRadiusValue, &left); - AdjustRight(bulgeCenterValue, horizontalRadiusValue, &right); - AdjustTop(bulgeCenterValue, verticalRadiusValue, &top); - AdjustBottom(bulgeCenterValue, verticalRadiusValue, &bottom); - contentBounds->setLTRB(left, top, right, bottom); + Path ellipsePath = {}; + // radius 需要加 1,如果 2 者相交只有一个点时,intersectPath.isEmpty 为 true + ConvertEllipseToPath(&ellipsePath, bulgeCenterValue.x, bulgeCenterValue.y, + horizontalRadiusValue + 1, verticalRadiusValue + 1); + Path boundsPath = {}; + boundsPath.addRect(left, top, right, bottom); + auto intersectPath = ellipsePath; + intersectPath.addPath(boundsPath, PathOp::Intersect); + // 凸出效果的椭圆与内容 bounds 没有交集,不改变尺寸 + if (intersectPath.isEmpty() && !intersectPath.isInverseFillType()) { + return; + } + // 计算凸出范围 + AdjustLeft(bulgeCenterValue, horizontalRadiusValue, &left); + AdjustRight(bulgeCenterValue, horizontalRadiusValue, &right); + AdjustTop(bulgeCenterValue, verticalRadiusValue, &top); + AdjustBottom(bulgeCenterValue, verticalRadiusValue, &bottom); + contentBounds->setLTRB(left, top, right, bottom); } void BulgeEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - horizontalRadius->excludeVaryingRanges(timeRanges); - verticalRadius->excludeVaryingRanges(timeRanges); - bulgeCenter->excludeVaryingRanges(timeRanges); - bulgeHeight->excludeVaryingRanges(timeRanges); - taperRadius->excludeVaryingRanges(timeRanges); - pinning->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + horizontalRadius->excludeVaryingRanges(timeRanges); + verticalRadius->excludeVaryingRanges(timeRanges); + bulgeCenter->excludeVaryingRanges(timeRanges); + bulgeHeight->excludeVaryingRanges(timeRanges); + taperRadius->excludeVaryingRanges(timeRanges); + pinning->excludeVaryingRanges(timeRanges); } bool BulgeEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(horizontalRadius != nullptr && verticalRadius != nullptr && - bulgeCenter != nullptr && bulgeHeight != nullptr && taperRadius != nullptr && - pinning != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(horizontalRadius != nullptr && verticalRadius != nullptr && + bulgeCenter != nullptr && bulgeHeight != nullptr && taperRadius != nullptr && + pinning != nullptr); } } // namespace pag diff --git a/src/base/effects/CornerPinEffect.cpp b/src/base/effects/CornerPinEffect.cpp index 775790f109..6b5e8fb15d 100644 --- a/src/base/effects/CornerPinEffect.cpp +++ b/src/base/effects/CornerPinEffect.cpp @@ -21,48 +21,48 @@ namespace pag { CornerPinEffect::~CornerPinEffect() { - delete upperLeft; - delete upperRight; - delete lowerLeft; - delete lowerRight; + delete upperLeft; + delete upperRight; + delete lowerLeft; + delete lowerRight; } bool CornerPinEffect::visibleAt(Frame) const { - return true; + return true; } void CornerPinEffect::transformBounds(Rect* contentBounds, const Point&, Frame layerFrame) const { - auto upperLeftValue = upperLeft->getValueAt(layerFrame); - auto upperRightValue = upperRight->getValueAt(layerFrame); - auto lowerLeftValue = lowerLeft->getValueAt(layerFrame); - auto lowerRightValue = lowerRight->getValueAt(layerFrame); + auto upperLeftValue = upperLeft->getValueAt(layerFrame); + auto upperRightValue = upperRight->getValueAt(layerFrame); + auto lowerLeftValue = lowerLeft->getValueAt(layerFrame); + auto lowerRightValue = lowerRight->getValueAt(layerFrame); - auto left = std::min(std::min(upperLeftValue.x, lowerLeftValue.x), - std::min(upperRightValue.x, lowerRightValue.x)); - auto top = std::min(std::min(upperLeftValue.y, lowerLeftValue.y), - std::min(upperRightValue.y, lowerRightValue.y)); - auto right = std::max(std::max(upperLeftValue.x, lowerLeftValue.x), - std::max(upperRightValue.x, lowerRightValue.x)); - auto bottom = std::max(std::max(upperLeftValue.y, lowerLeftValue.y), - std::max(upperRightValue.y, lowerRightValue.y)); + auto left = std::min(std::min(upperLeftValue.x, lowerLeftValue.x), + std::min(upperRightValue.x, lowerRightValue.x)); + auto top = std::min(std::min(upperLeftValue.y, lowerLeftValue.y), + std::min(upperRightValue.y, lowerRightValue.y)); + auto right = std::max(std::max(upperLeftValue.x, lowerLeftValue.x), + std::max(upperRightValue.x, lowerRightValue.x)); + auto bottom = std::max(std::max(upperLeftValue.y, lowerLeftValue.y), + std::max(upperRightValue.y, lowerRightValue.y)); - contentBounds->setLTRB(left, top, right, bottom); + contentBounds->setLTRB(left, top, right, bottom); } void CornerPinEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - upperLeft->excludeVaryingRanges(timeRanges); - upperRight->excludeVaryingRanges(timeRanges); - lowerLeft->excludeVaryingRanges(timeRanges); - lowerRight->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + upperLeft->excludeVaryingRanges(timeRanges); + upperRight->excludeVaryingRanges(timeRanges); + lowerLeft->excludeVaryingRanges(timeRanges); + lowerRight->excludeVaryingRanges(timeRanges); } bool CornerPinEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(upperLeft != nullptr && upperRight != nullptr && lowerLeft != nullptr && - lowerRight != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(upperLeft != nullptr && upperRight != nullptr && lowerLeft != nullptr && + lowerRight != nullptr); } } // namespace pag diff --git a/src/base/effects/DisplacementMapEffect.cpp b/src/base/effects/DisplacementMapEffect.cpp index 44a8640d79..c24408495a 100644 --- a/src/base/effects/DisplacementMapEffect.cpp +++ b/src/base/effects/DisplacementMapEffect.cpp @@ -21,58 +21,58 @@ namespace pag { DisplacementMapEffect::~DisplacementMapEffect() { - delete useForHorizontalDisplacement; - delete maxHorizontalDisplacement; - delete useForVerticalDisplacement; - delete maxVerticalDisplacement; - delete displacementMapBehavior; - delete edgeBehavior; - delete expandOutput; + delete useForHorizontalDisplacement; + delete maxHorizontalDisplacement; + delete useForVerticalDisplacement; + delete maxVerticalDisplacement; + delete displacementMapBehavior; + delete edgeBehavior; + delete expandOutput; } bool DisplacementMapEffect::visibleAt(Frame layerFrame) const { - if (displacementMapLayer == nullptr) { - return false; - } - // DisplacementMap特效只支持视频序列帧或者图片序列帧。 - if (displacementMapLayer->type() == LayerType::PreCompose) { - auto preComposeLayer = static_cast(displacementMapLayer); - auto composition = preComposeLayer->composition; - if (composition->type() == CompositionType::Video || - composition->type() == CompositionType::Bitmap) { - auto mapContentFrame = layerFrame - displacementMapLayer->startTime; - if (mapContentFrame < 0 || mapContentFrame >= displacementMapLayer->duration) { + if (displacementMapLayer == nullptr) { return false; - } - return maxHorizontalDisplacement->getValueAt(layerFrame) != 0 || - maxVerticalDisplacement->getValueAt(layerFrame) != 0; } - } - return false; + // DisplacementMap特效只支持视频序列帧或者图片序列帧。 + if (displacementMapLayer->type() == LayerType::PreCompose) { + auto preComposeLayer = static_cast(displacementMapLayer); + auto composition = preComposeLayer->composition; + if (composition->type() == CompositionType::Video || + composition->type() == CompositionType::Bitmap) { + auto mapContentFrame = layerFrame - displacementMapLayer->startTime; + if (mapContentFrame < 0 || mapContentFrame >= displacementMapLayer->duration) { + return false; + } + return maxHorizontalDisplacement->getValueAt(layerFrame) != 0 || + maxVerticalDisplacement->getValueAt(layerFrame) != 0; + } + } + return false; } void DisplacementMapEffect::transformBounds(Rect*, const Point&, Frame) const { } void DisplacementMapEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - useForHorizontalDisplacement->excludeVaryingRanges(timeRanges); - maxHorizontalDisplacement->excludeVaryingRanges(timeRanges); - useForVerticalDisplacement->excludeVaryingRanges(timeRanges); - maxVerticalDisplacement->excludeVaryingRanges(timeRanges); - displacementMapBehavior->excludeVaryingRanges(timeRanges); - edgeBehavior->excludeVaryingRanges(timeRanges); - expandOutput->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + useForHorizontalDisplacement->excludeVaryingRanges(timeRanges); + maxHorizontalDisplacement->excludeVaryingRanges(timeRanges); + useForVerticalDisplacement->excludeVaryingRanges(timeRanges); + maxVerticalDisplacement->excludeVaryingRanges(timeRanges); + displacementMapBehavior->excludeVaryingRanges(timeRanges); + edgeBehavior->excludeVaryingRanges(timeRanges); + expandOutput->excludeVaryingRanges(timeRanges); } bool DisplacementMapEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(useForHorizontalDisplacement != nullptr && maxHorizontalDisplacement != nullptr && - useForVerticalDisplacement != nullptr && maxVerticalDisplacement != nullptr && - displacementMapBehavior != nullptr && edgeBehavior != nullptr && - expandOutput != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(useForHorizontalDisplacement != nullptr && maxHorizontalDisplacement != nullptr && + useForVerticalDisplacement != nullptr && maxVerticalDisplacement != nullptr && + displacementMapBehavior != nullptr && edgeBehavior != nullptr && + expandOutput != nullptr); } } // namespace pag diff --git a/src/base/effects/Effect.cpp b/src/base/effects/Effect.cpp index 7f715a90a2..415d090ee2 100644 --- a/src/base/effects/Effect.cpp +++ b/src/base/effects/Effect.cpp @@ -25,22 +25,22 @@ Effect::Effect() : uniqueID(UniqueID::Next()) { } Effect::~Effect() { - delete effectOpacity; + delete effectOpacity; } void Effect::excludeVaryingRanges(std::vector* timeRanges) const { - if (effectOpacity != nullptr) { - effectOpacity->excludeVaryingRanges(timeRanges); - } + if (effectOpacity != nullptr) { + effectOpacity->excludeVaryingRanges(timeRanges); + } } bool Effect::verify() const { - for (auto mask : maskReferences) { - if (mask == nullptr) { - VerifyFailed(); - return false; + for (auto mask : maskReferences) { + if (mask == nullptr) { + VerifyFailed(); + return false; + } } - } - return true; + return true; } } // namespace pag diff --git a/src/base/effects/FastBlurEffect.cpp b/src/base/effects/FastBlurEffect.cpp index 77cfc46e11..c0bfaf9d24 100644 --- a/src/base/effects/FastBlurEffect.cpp +++ b/src/base/effects/FastBlurEffect.cpp @@ -21,49 +21,49 @@ namespace pag { FastBlurEffect::~FastBlurEffect() { - delete blurriness; - delete blurDimensions; - delete repeatEdgePixels; + delete blurriness; + delete blurDimensions; + delete repeatEdgePixels; } bool FastBlurEffect::visibleAt(Frame layerFrame) const { - return blurriness->getValueAt(layerFrame) != 0; + return blurriness->getValueAt(layerFrame) != 0; } void FastBlurEffect::transformBounds(Rect* contentBounds, const Point& filterScale, Frame layerFrame) const { - auto repeatEdge = repeatEdgePixels->getValueAt(layerFrame); - if (repeatEdge) { - return; - } - auto direction = blurDimensions->getValueAt(layerFrame); - auto intensity = blurriness->getValueAt(layerFrame); - auto blurrinessX = intensity * filterScale.x; - auto blurrinessY = intensity * filterScale.y; - auto expandX = (direction == BlurDimensionsDirection::All || - direction == BlurDimensionsDirection::Horizontal) - ? blurrinessX - : 0.0; - auto expandY = - (direction == BlurDimensionsDirection::All || direction == BlurDimensionsDirection::Vertical) - ? blurrinessY - : 0.0; - contentBounds->outset(expandX, expandY); + auto repeatEdge = repeatEdgePixels->getValueAt(layerFrame); + if (repeatEdge) { + return; + } + auto direction = blurDimensions->getValueAt(layerFrame); + auto intensity = blurriness->getValueAt(layerFrame); + auto blurrinessX = intensity * filterScale.x; + auto blurrinessY = intensity * filterScale.y; + auto expandX = (direction == BlurDimensionsDirection::All || + direction == BlurDimensionsDirection::Horizontal) + ? blurrinessX + : 0.0; + auto expandY = + (direction == BlurDimensionsDirection::All || direction == BlurDimensionsDirection::Vertical) + ? blurrinessY + : 0.0; + contentBounds->outset(expandX, expandY); } void FastBlurEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - blurriness->excludeVaryingRanges(timeRanges); - blurDimensions->excludeVaryingRanges(timeRanges); - repeatEdgePixels->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + blurriness->excludeVaryingRanges(timeRanges); + blurDimensions->excludeVaryingRanges(timeRanges); + repeatEdgePixels->excludeVaryingRanges(timeRanges); } bool FastBlurEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(blurriness != nullptr && blurDimensions != nullptr && - repeatEdgePixels != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(blurriness != nullptr && blurDimensions != nullptr && + repeatEdgePixels != nullptr); } } // namespace pag diff --git a/src/base/effects/GlowEffect.cpp b/src/base/effects/GlowEffect.cpp index 10450eb511..a35c9960bc 100644 --- a/src/base/effects/GlowEffect.cpp +++ b/src/base/effects/GlowEffect.cpp @@ -21,31 +21,31 @@ namespace pag { GlowEffect::~GlowEffect() { - delete glowThreshold; - delete glowRadius; - delete glowIntensity; + delete glowThreshold; + delete glowRadius; + delete glowIntensity; } bool GlowEffect::visibleAt(Frame layerFrame) const { - auto threshold = glowThreshold->getValueAt(layerFrame); - return threshold < 1.0f; + auto threshold = glowThreshold->getValueAt(layerFrame); + return threshold < 1.0f; } void GlowEffect::transformBounds(Rect*, const Point&, Frame) const { } void GlowEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - glowThreshold->excludeVaryingRanges(timeRanges); - glowRadius->excludeVaryingRanges(timeRanges); - glowIntensity->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + glowThreshold->excludeVaryingRanges(timeRanges); + glowRadius->excludeVaryingRanges(timeRanges); + glowIntensity->excludeVaryingRanges(timeRanges); } bool GlowEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(glowThreshold != nullptr && glowRadius != nullptr && glowIntensity != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(glowThreshold != nullptr && glowRadius != nullptr && glowIntensity != nullptr); } } // namespace pag diff --git a/src/base/effects/LevelsIndividualEffect.cpp b/src/base/effects/LevelsIndividualEffect.cpp index db2bda616f..f0b8586c8d 100644 --- a/src/base/effects/LevelsIndividualEffect.cpp +++ b/src/base/effects/LevelsIndividualEffect.cpp @@ -21,82 +21,82 @@ namespace pag { LevelsIndividualEffect::~LevelsIndividualEffect() { - // RGB - delete inputBlack; - delete inputWhite; - delete gamma; - delete outputBlack; - delete outputWhite; - // Red - delete redInputBlack; - delete redInputWhite; - delete redGamma; - delete redOutputBlack; - delete redOutputWhite; - // Green - delete greenInputBlack; - delete greenInputWhite; - delete greenGamma; - delete greenOutputBlack; - delete greenOutputWhite; - // Blue - delete blueInputBlack; - delete blueInputWhite; - delete blueGamma; - delete blueOutputBlack; - delete blueOutputWhite; + // RGB + delete inputBlack; + delete inputWhite; + delete gamma; + delete outputBlack; + delete outputWhite; + // Red + delete redInputBlack; + delete redInputWhite; + delete redGamma; + delete redOutputBlack; + delete redOutputWhite; + // Green + delete greenInputBlack; + delete greenInputWhite; + delete greenGamma; + delete greenOutputBlack; + delete greenOutputWhite; + // Blue + delete blueInputBlack; + delete blueInputWhite; + delete blueGamma; + delete blueOutputBlack; + delete blueOutputWhite; } bool LevelsIndividualEffect::visibleAt(Frame) const { - return true; + return true; } void LevelsIndividualEffect::transformBounds(Rect*, const Point&, Frame) const { } void LevelsIndividualEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - // RGB - inputBlack->excludeVaryingRanges(timeRanges); - inputWhite->excludeVaryingRanges(timeRanges); - gamma->excludeVaryingRanges(timeRanges); - outputBlack->excludeVaryingRanges(timeRanges); - outputWhite->excludeVaryingRanges(timeRanges); - // Red - redInputBlack->excludeVaryingRanges(timeRanges); - redInputWhite->excludeVaryingRanges(timeRanges); - redGamma->excludeVaryingRanges(timeRanges); - redOutputBlack->excludeVaryingRanges(timeRanges); - redOutputWhite->excludeVaryingRanges(timeRanges); - // Green - greenInputBlack->excludeVaryingRanges(timeRanges); - greenInputWhite->excludeVaryingRanges(timeRanges); - greenGamma->excludeVaryingRanges(timeRanges); - greenOutputBlack->excludeVaryingRanges(timeRanges); - greenOutputWhite->excludeVaryingRanges(timeRanges); - // Blue - blueInputBlack->excludeVaryingRanges(timeRanges); - blueInputWhite->excludeVaryingRanges(timeRanges); - blueGamma->excludeVaryingRanges(timeRanges); - blueOutputBlack->excludeVaryingRanges(timeRanges); - blueOutputWhite->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + // RGB + inputBlack->excludeVaryingRanges(timeRanges); + inputWhite->excludeVaryingRanges(timeRanges); + gamma->excludeVaryingRanges(timeRanges); + outputBlack->excludeVaryingRanges(timeRanges); + outputWhite->excludeVaryingRanges(timeRanges); + // Red + redInputBlack->excludeVaryingRanges(timeRanges); + redInputWhite->excludeVaryingRanges(timeRanges); + redGamma->excludeVaryingRanges(timeRanges); + redOutputBlack->excludeVaryingRanges(timeRanges); + redOutputWhite->excludeVaryingRanges(timeRanges); + // Green + greenInputBlack->excludeVaryingRanges(timeRanges); + greenInputWhite->excludeVaryingRanges(timeRanges); + greenGamma->excludeVaryingRanges(timeRanges); + greenOutputBlack->excludeVaryingRanges(timeRanges); + greenOutputWhite->excludeVaryingRanges(timeRanges); + // Blue + blueInputBlack->excludeVaryingRanges(timeRanges); + blueInputWhite->excludeVaryingRanges(timeRanges); + blueGamma->excludeVaryingRanges(timeRanges); + blueOutputBlack->excludeVaryingRanges(timeRanges); + blueOutputWhite->excludeVaryingRanges(timeRanges); } static bool calculate5and(bool a, bool b, bool c, bool d, bool e) { - return a && b && c && d && e; + return a && b && c && d && e; } bool LevelsIndividualEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - auto rgb = calculate5and(inputBlack, inputWhite, gamma, outputBlack, outputWhite); - auto red = calculate5and(redInputBlack, redInputWhite, redGamma, redOutputBlack, redOutputWhite); - auto green = calculate5and(greenInputBlack, greenInputWhite, greenGamma, greenOutputBlack, - greenOutputWhite); - auto blue = - calculate5and(blueInputBlack, blueInputWhite, blueGamma, blueOutputBlack, blueOutputWhite); - VerifyAndReturn(calculate5and(rgb, red, green, blue, 1)); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + auto rgb = calculate5and(inputBlack, inputWhite, gamma, outputBlack, outputWhite); + auto red = calculate5and(redInputBlack, redInputWhite, redGamma, redOutputBlack, redOutputWhite); + auto green = calculate5and(greenInputBlack, greenInputWhite, greenGamma, greenOutputBlack, + greenOutputWhite); + auto blue = + calculate5and(blueInputBlack, blueInputWhite, blueGamma, blueOutputBlack, blueOutputWhite); + VerifyAndReturn(calculate5and(rgb, red, green, blue, 1)); } } // namespace pag diff --git a/src/base/effects/MosaicEffect.cpp b/src/base/effects/MosaicEffect.cpp index 233100aa2e..7abf4481c4 100644 --- a/src/base/effects/MosaicEffect.cpp +++ b/src/base/effects/MosaicEffect.cpp @@ -21,31 +21,31 @@ namespace pag { MosaicEffect::~MosaicEffect() { - delete horizontalBlocks; - delete verticalBlocks; - delete sharpColors; + delete horizontalBlocks; + delete verticalBlocks; + delete sharpColors; } bool MosaicEffect::visibleAt(Frame) const { - return true; + return true; } void MosaicEffect::transformBounds(Rect*, const Point&, Frame) const { } void MosaicEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - horizontalBlocks->excludeVaryingRanges(timeRanges); - verticalBlocks->excludeVaryingRanges(timeRanges); - sharpColors->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + horizontalBlocks->excludeVaryingRanges(timeRanges); + verticalBlocks->excludeVaryingRanges(timeRanges); + sharpColors->excludeVaryingRanges(timeRanges); } bool MosaicEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(horizontalBlocks != nullptr && verticalBlocks != nullptr && - sharpColors != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(horizontalBlocks != nullptr && verticalBlocks != nullptr && + sharpColors != nullptr); } } // namespace pag diff --git a/src/base/effects/MotionTileEffect.cpp b/src/base/effects/MotionTileEffect.cpp index 862e1cc61b..d56d8edbdd 100644 --- a/src/base/effects/MotionTileEffect.cpp +++ b/src/base/effects/MotionTileEffect.cpp @@ -22,49 +22,49 @@ namespace pag { MotionTileEffect::~MotionTileEffect() { - delete tileCenter; - delete tileWidth; - delete tileHeight; - delete outputWidth; - delete outputHeight; - delete mirrorEdges; - delete phase; - delete horizontalPhaseShift; + delete tileCenter; + delete tileWidth; + delete tileHeight; + delete outputWidth; + delete outputHeight; + delete mirrorEdges; + delete phase; + delete horizontalPhaseShift; } bool MotionTileEffect::visibleAt(Frame) const { - return true; + return true; } void MotionTileEffect::transformBounds(Rect* contentBounds, const Point&, Frame layerFrame) const { - auto outputWidthValue = outputWidth->getValueAt(layerFrame); - auto outputHeightValue = outputHeight->getValueAt(layerFrame); - auto width = contentBounds->width() * outputWidthValue / 100.0f; - auto height = contentBounds->height() * outputHeightValue / 100.0f; - auto x = contentBounds->x() + (contentBounds->width() - width) * 0.5f; - auto y = contentBounds->y() + (contentBounds->height() - height) * 0.5f; - contentBounds->setXYWH(x, y, width, height); + auto outputWidthValue = outputWidth->getValueAt(layerFrame); + auto outputHeightValue = outputHeight->getValueAt(layerFrame); + auto width = contentBounds->width() * outputWidthValue / 100.0f; + auto height = contentBounds->height() * outputHeightValue / 100.0f; + auto x = contentBounds->x() + (contentBounds->width() - width) * 0.5f; + auto y = contentBounds->y() + (contentBounds->height() - height) * 0.5f; + contentBounds->setXYWH(x, y, width, height); } void MotionTileEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - tileCenter->excludeVaryingRanges(timeRanges); - tileWidth->excludeVaryingRanges(timeRanges); - tileHeight->excludeVaryingRanges(timeRanges); - outputWidth->excludeVaryingRanges(timeRanges); - outputHeight->excludeVaryingRanges(timeRanges); - mirrorEdges->excludeVaryingRanges(timeRanges); - phase->excludeVaryingRanges(timeRanges); - horizontalPhaseShift->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + tileCenter->excludeVaryingRanges(timeRanges); + tileWidth->excludeVaryingRanges(timeRanges); + tileHeight->excludeVaryingRanges(timeRanges); + outputWidth->excludeVaryingRanges(timeRanges); + outputHeight->excludeVaryingRanges(timeRanges); + mirrorEdges->excludeVaryingRanges(timeRanges); + phase->excludeVaryingRanges(timeRanges); + horizontalPhaseShift->excludeVaryingRanges(timeRanges); } bool MotionTileEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(tileCenter != nullptr && tileWidth != nullptr && tileHeight != nullptr && - outputWidth != nullptr && outputHeight != nullptr && mirrorEdges != nullptr && - phase != nullptr && horizontalPhaseShift != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(tileCenter != nullptr && tileWidth != nullptr && tileHeight != nullptr && + outputWidth != nullptr && outputHeight != nullptr && mirrorEdges != nullptr && + phase != nullptr && horizontalPhaseShift != nullptr); } } // namespace pag diff --git a/src/base/effects/RadialBlurEffect.cpp b/src/base/effects/RadialBlurEffect.cpp index f6e456e772..8ce11de425 100644 --- a/src/base/effects/RadialBlurEffect.cpp +++ b/src/base/effects/RadialBlurEffect.cpp @@ -21,34 +21,34 @@ namespace pag { RadialBlurEffect::~RadialBlurEffect() { - delete amount; - delete center; - delete mode; - delete antialias; + delete amount; + delete center; + delete mode; + delete antialias; } bool RadialBlurEffect::visibleAt(Frame layerFrame) const { - auto amountValue = amount->getValueAt(layerFrame); - return amountValue != 0; + auto amountValue = amount->getValueAt(layerFrame); + return amountValue != 0; } void RadialBlurEffect::transformBounds(Rect*, const Point&, Frame) const { } void RadialBlurEffect::excludeVaryingRanges(std::vector* timeRanges) const { - Effect::excludeVaryingRanges(timeRanges); - amount->excludeVaryingRanges(timeRanges); - center->excludeVaryingRanges(timeRanges); - mode->excludeVaryingRanges(timeRanges); - antialias->excludeVaryingRanges(timeRanges); + Effect::excludeVaryingRanges(timeRanges); + amount->excludeVaryingRanges(timeRanges); + center->excludeVaryingRanges(timeRanges); + mode->excludeVaryingRanges(timeRanges); + antialias->excludeVaryingRanges(timeRanges); } bool RadialBlurEffect::verify() const { - if (!Effect::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(amount != nullptr && center != nullptr && mode != nullptr && - antialias != nullptr); + if (!Effect::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(amount != nullptr && center != nullptr && mode != nullptr && + antialias != nullptr); } } // namespace pag diff --git a/src/base/keyframes/MultiDimensionPointKeyframe.cpp b/src/base/keyframes/MultiDimensionPointKeyframe.cpp index 6420858409..f579c723a9 100644 --- a/src/base/keyframes/MultiDimensionPointKeyframe.cpp +++ b/src/base/keyframes/MultiDimensionPointKeyframe.cpp @@ -20,27 +20,27 @@ namespace pag { MultiDimensionPointKeyframe::~MultiDimensionPointKeyframe() { - delete xInterpolator; - delete yInterpolator; + delete xInterpolator; + delete yInterpolator; } void MultiDimensionPointKeyframe::initialize() { - if (interpolationType == KeyframeInterpolationType::Bezier) { - xInterpolator = new BezierEasing(this->bezierOut[0], this->bezierIn[0]); - yInterpolator = new BezierEasing(this->bezierOut[1], this->bezierIn[1]); - } else { - xInterpolator = new Interpolator(); - yInterpolator = new Interpolator(); - } + if (interpolationType == KeyframeInterpolationType::Bezier) { + xInterpolator = new BezierEasing(this->bezierOut[0], this->bezierIn[0]); + yInterpolator = new BezierEasing(this->bezierOut[1], this->bezierIn[1]); + } else { + xInterpolator = new Interpolator(); + yInterpolator = new Interpolator(); + } } Point MultiDimensionPointKeyframe::getValueAt(Frame time) { - auto progress = static_cast(time - this->startTime) / (this->endTime - this->startTime); - auto xProgress = xInterpolator->getInterpolation(progress); - auto yProgress = yInterpolator->getInterpolation(progress); - auto x = Interpolate(this->startValue.x, this->endValue.x, xProgress); - auto y = Interpolate(this->startValue.y, this->endValue.y, yProgress); - return {x, y}; + auto progress = static_cast(time - this->startTime) / (this->endTime - this->startTime); + auto xProgress = xInterpolator->getInterpolation(progress); + auto yProgress = yInterpolator->getInterpolation(progress); + auto x = Interpolate(this->startValue.x, this->endValue.x, xProgress); + auto y = Interpolate(this->startValue.y, this->endValue.y, yProgress); + return {x, y}; } } // namespace pag \ No newline at end of file diff --git a/src/base/keyframes/MultiDimensionPointKeyframe.h b/src/base/keyframes/MultiDimensionPointKeyframe.h index d9a0c23cc4..fcf4011aa5 100644 --- a/src/base/keyframes/MultiDimensionPointKeyframe.h +++ b/src/base/keyframes/MultiDimensionPointKeyframe.h @@ -23,15 +23,15 @@ namespace pag { class MultiDimensionPointKeyframe : public Keyframe { - public: - ~MultiDimensionPointKeyframe() override; +public: + ~MultiDimensionPointKeyframe() override; - void initialize() override; + void initialize() override; - Point getValueAt(Frame time) override; + Point getValueAt(Frame time) override; - private: - Interpolator* xInterpolator = nullptr; - Interpolator* yInterpolator = nullptr; +private: + Interpolator* xInterpolator = nullptr; + Interpolator* yInterpolator = nullptr; }; } // namespace pag diff --git a/src/base/keyframes/SingleEaseKeyframe.h b/src/base/keyframes/SingleEaseKeyframe.h index b83713fbb9..743ad85315 100644 --- a/src/base/keyframes/SingleEaseKeyframe.h +++ b/src/base/keyframes/SingleEaseKeyframe.h @@ -24,30 +24,30 @@ namespace pag { template class SingleEaseKeyframe : public Keyframe { - public: - ~SingleEaseKeyframe() override { - delete interpolator; - } +public: + ~SingleEaseKeyframe() override { + delete interpolator; + } - void initialize() override { - if (this->interpolationType == KeyframeInterpolationType::Bezier) { - interpolator = new BezierEasing(this->bezierOut[0], this->bezierIn[0]); - } else { - interpolator = new Interpolator(); + void initialize() override { + if (this->interpolationType == KeyframeInterpolationType::Bezier) { + interpolator = new BezierEasing(this->bezierOut[0], this->bezierIn[0]); + } else { + interpolator = new Interpolator(); + } } - } - float getProgress(Frame time) { - auto progress = static_cast(time - this->startTime) / (this->endTime - this->startTime); - return interpolator->getInterpolation(progress); - } + float getProgress(Frame time) { + auto progress = static_cast(time - this->startTime) / (this->endTime - this->startTime); + return interpolator->getInterpolation(progress); + } - T getValueAt(Frame time) override { - auto progress = getProgress(time); - return Interpolate(this->startValue, this->endValue, progress); - } + T getValueAt(Frame time) override { + auto progress = getProgress(time); + return Interpolate(this->startValue, this->endValue, progress); + } - private: - Interpolator* interpolator = nullptr; +private: + Interpolator* interpolator = nullptr; }; } // namespace pag diff --git a/src/base/keyframes/SpatialPointKeyframe.cpp b/src/base/keyframes/SpatialPointKeyframe.cpp index 4da0e974f2..4c141a0bf9 100644 --- a/src/base/keyframes/SpatialPointKeyframe.cpp +++ b/src/base/keyframes/SpatialPointKeyframe.cpp @@ -20,13 +20,13 @@ namespace pag { void SpatialPointKeyframe::initialize() { - SingleEaseKeyframe::initialize(); - spatialBezier = - BezierPath::Build(startValue, startValue + spatialOut, endValue + spatialIn, endValue, 0.05f); + SingleEaseKeyframe::initialize(); + spatialBezier = + BezierPath::Build(startValue, startValue + spatialOut, endValue + spatialIn, endValue, 0.05f); } Point SpatialPointKeyframe::getValueAt(Frame time) { - auto progress = getProgress(time); - return spatialBezier->getPosition(progress); + auto progress = getProgress(time); + return spatialBezier->getPosition(progress); } } // namespace pag \ No newline at end of file diff --git a/src/base/keyframes/SpatialPointKeyframe.h b/src/base/keyframes/SpatialPointKeyframe.h index 29af47af8f..fe4cde7d5b 100644 --- a/src/base/keyframes/SpatialPointKeyframe.h +++ b/src/base/keyframes/SpatialPointKeyframe.h @@ -22,11 +22,11 @@ namespace pag { class SpatialPointKeyframe : public SingleEaseKeyframe { - public: - void initialize() override; - Point getValueAt(Frame time) override; +public: + void initialize() override; + Point getValueAt(Frame time) override; - private: - std::shared_ptr spatialBezier = nullptr; +private: + std::shared_ptr spatialBezier = nullptr; }; } // namespace pag diff --git a/src/base/layerStyles/DropShadowStyle.cpp b/src/base/layerStyles/DropShadowStyle.cpp index 6a87f8bade..1d11d0aab3 100644 --- a/src/base/layerStyles/DropShadowStyle.cpp +++ b/src/base/layerStyles/DropShadowStyle.cpp @@ -22,49 +22,49 @@ namespace pag { DropShadowStyle::~DropShadowStyle() { - delete blendMode; - delete color; - delete opacity; - delete angle; - delete distance; - delete size; - delete spread; + delete blendMode; + delete color; + delete opacity; + delete angle; + delete distance; + delete size; + delete spread; } bool DropShadowStyle::visibleAt(Frame layerFrame) const { - auto distanceValue = distance->getValueAt(layerFrame); - auto sizeValue = size->getValueAt(layerFrame); - return distanceValue > 0 || sizeValue > 0; + auto distanceValue = distance->getValueAt(layerFrame); + auto sizeValue = size->getValueAt(layerFrame); + return distanceValue > 0 || sizeValue > 0; } void DropShadowStyle::transformBounds(Rect* contentBounds, const Point& filterScale, Frame layerFrame) const { - auto angleValue = angle->getValueAt(layerFrame); - auto distanceValue = distance->getValueAt(layerFrame); - auto sizeValue = size->getValueAt(layerFrame); - auto radians = DegreesToRadians(angleValue - 180); - float offsetX = cosf(radians) * distanceValue; - float offsetY = -sinf(radians) * distanceValue; - contentBounds->offset(offsetX * filterScale.x, offsetY * filterScale.y); - contentBounds->outset(sizeValue * filterScale.x, sizeValue * filterScale.y); + auto angleValue = angle->getValueAt(layerFrame); + auto distanceValue = distance->getValueAt(layerFrame); + auto sizeValue = size->getValueAt(layerFrame); + auto radians = DegreesToRadians(angleValue - 180); + float offsetX = cosf(radians) * distanceValue; + float offsetY = -sinf(radians) * distanceValue; + contentBounds->offset(offsetX * filterScale.x, offsetY * filterScale.y); + contentBounds->outset(sizeValue * filterScale.x, sizeValue * filterScale.y); } void DropShadowStyle::excludeVaryingRanges(std::vector* timeRanges) const { - blendMode->excludeVaryingRanges(timeRanges); - color->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); - angle->excludeVaryingRanges(timeRanges); - distance->excludeVaryingRanges(timeRanges); - size->excludeVaryingRanges(timeRanges); - spread->excludeVaryingRanges(timeRanges); + blendMode->excludeVaryingRanges(timeRanges); + color->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); + angle->excludeVaryingRanges(timeRanges); + distance->excludeVaryingRanges(timeRanges); + size->excludeVaryingRanges(timeRanges); + spread->excludeVaryingRanges(timeRanges); } bool DropShadowStyle::verify() const { - if (!LayerStyle::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(blendMode != nullptr && color != nullptr && opacity != nullptr && - angle != nullptr && distance != nullptr && size != nullptr && spread != nullptr); + if (!LayerStyle::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(blendMode != nullptr && color != nullptr && opacity != nullptr && + angle != nullptr && distance != nullptr && size != nullptr && spread != nullptr); } } // namespace pag diff --git a/src/base/layerStyles/StrokeStyle.cpp b/src/base/layerStyles/StrokeStyle.cpp index 61f45271d6..55904a06e5 100644 --- a/src/base/layerStyles/StrokeStyle.cpp +++ b/src/base/layerStyles/StrokeStyle.cpp @@ -21,34 +21,34 @@ namespace pag { StrokeStyle::~StrokeStyle() { - delete blendMode; - delete color; - delete size; - delete opacity; - delete position; + delete blendMode; + delete color; + delete size; + delete opacity; + delete position; } bool StrokeStyle::visibleAt(Frame) const { - return false; + return false; } void StrokeStyle::transformBounds(Rect*, const Point&, Frame) const { } void StrokeStyle::excludeVaryingRanges(std::vector* timeRanges) const { - blendMode->excludeVaryingRanges(timeRanges); - color->excludeVaryingRanges(timeRanges); - size->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); - position->excludeVaryingRanges(timeRanges); + blendMode->excludeVaryingRanges(timeRanges); + color->excludeVaryingRanges(timeRanges); + size->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); } bool StrokeStyle::verify() const { - if (!LayerStyle::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(blendMode != nullptr && color != nullptr && size != nullptr && - opacity != nullptr && position != nullptr); + if (!LayerStyle::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(blendMode != nullptr && color != nullptr && size != nullptr && + opacity != nullptr && position != nullptr); } } // namespace pag diff --git a/src/base/shapes/EllipseElement.cpp b/src/base/shapes/EllipseElement.cpp index c943404d4b..50a87a5288 100644 --- a/src/base/shapes/EllipseElement.cpp +++ b/src/base/shapes/EllipseElement.cpp @@ -21,20 +21,20 @@ namespace pag { EllipseElement::~EllipseElement() { - delete size; - delete position; + delete size; + delete position; } void EllipseElement::excludeVaryingRanges(std::vector* timeRanges) const { - position->excludeVaryingRanges(timeRanges); - size->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); + size->excludeVaryingRanges(timeRanges); } bool EllipseElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(position != nullptr && size != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(position != nullptr && size != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/FillElement.cpp b/src/base/shapes/FillElement.cpp index d87fbe1697..e8fa081736 100644 --- a/src/base/shapes/FillElement.cpp +++ b/src/base/shapes/FillElement.cpp @@ -21,20 +21,20 @@ namespace pag { FillElement::~FillElement() { - delete color; - delete opacity; + delete color; + delete opacity; } void FillElement::excludeVaryingRanges(std::vector* timeRanges) const { - color->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); + color->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); } bool FillElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(color != nullptr && opacity != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(color != nullptr && opacity != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/GradientFillElement.cpp b/src/base/shapes/GradientFillElement.cpp index dcd51df1f4..7d73b4c8c1 100644 --- a/src/base/shapes/GradientFillElement.cpp +++ b/src/base/shapes/GradientFillElement.cpp @@ -21,25 +21,25 @@ namespace pag { GradientFillElement::~GradientFillElement() { - delete startPoint; - delete endPoint; - delete colors; - delete opacity; + delete startPoint; + delete endPoint; + delete colors; + delete opacity; } void GradientFillElement::excludeVaryingRanges(std::vector* timeRanges) const { - startPoint->excludeVaryingRanges(timeRanges); - endPoint->excludeVaryingRanges(timeRanges); - colors->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); + startPoint->excludeVaryingRanges(timeRanges); + endPoint->excludeVaryingRanges(timeRanges); + colors->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); } bool GradientFillElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(startPoint != nullptr && endPoint != nullptr && colors != nullptr && - opacity != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(startPoint != nullptr && endPoint != nullptr && colors != nullptr && + opacity != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/GradientStrokeElement.cpp b/src/base/shapes/GradientStrokeElement.cpp index cdb4f593cc..6b01dd0ee2 100644 --- a/src/base/shapes/GradientStrokeElement.cpp +++ b/src/base/shapes/GradientStrokeElement.cpp @@ -21,45 +21,45 @@ namespace pag { GradientStrokeElement::~GradientStrokeElement() { - delete miterLimit; - delete startPoint; - delete endPoint; - delete colors; - delete opacity; - delete strokeWidth; - delete dashOffset; - for (auto& dash : dashes) { - delete dash; - } + delete miterLimit; + delete startPoint; + delete endPoint; + delete colors; + delete opacity; + delete strokeWidth; + delete dashOffset; + for (auto& dash : dashes) { + delete dash; + } } void GradientStrokeElement::excludeVaryingRanges(std::vector* timeRanges) const { - miterLimit->excludeVaryingRanges(timeRanges); - startPoint->excludeVaryingRanges(timeRanges); - endPoint->excludeVaryingRanges(timeRanges); - colors->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); - strokeWidth->excludeVaryingRanges(timeRanges); - if (!dashes.empty()) { - dashOffset->excludeVaryingRanges(timeRanges); - for (auto& property : dashes) { - property->excludeVaryingRanges(timeRanges); + miterLimit->excludeVaryingRanges(timeRanges); + startPoint->excludeVaryingRanges(timeRanges); + endPoint->excludeVaryingRanges(timeRanges); + colors->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); + strokeWidth->excludeVaryingRanges(timeRanges); + if (!dashes.empty()) { + dashOffset->excludeVaryingRanges(timeRanges); + for (auto& property : dashes) { + property->excludeVaryingRanges(timeRanges); + } } - } } bool GradientStrokeElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - for (auto dash : dashes) { - if (dash == nullptr) { - VerifyFailed(); - return false; + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + for (auto dash : dashes) { + if (dash == nullptr) { + VerifyFailed(); + return false; + } } - } - VerifyAndReturn(miterLimit != nullptr && startPoint != nullptr && endPoint != nullptr && - colors != nullptr && opacity != nullptr && strokeWidth != nullptr); + VerifyAndReturn(miterLimit != nullptr && startPoint != nullptr && endPoint != nullptr && + colors != nullptr && opacity != nullptr && strokeWidth != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/PolyStarElement.cpp b/src/base/shapes/PolyStarElement.cpp index 7bace9602e..b1901ec42c 100644 --- a/src/base/shapes/PolyStarElement.cpp +++ b/src/base/shapes/PolyStarElement.cpp @@ -21,32 +21,32 @@ namespace pag { PolyStarElement::~PolyStarElement() { - delete points; - delete position; - delete rotation; - delete innerRadius; - delete outerRadius; - delete innerRoundness; - delete outerRoundness; + delete points; + delete position; + delete rotation; + delete innerRadius; + delete outerRadius; + delete innerRoundness; + delete outerRoundness; } void PolyStarElement::excludeVaryingRanges(std::vector* timeRanges) const { - points->excludeVaryingRanges(timeRanges); - position->excludeVaryingRanges(timeRanges); - rotation->excludeVaryingRanges(timeRanges); - innerRadius->excludeVaryingRanges(timeRanges); - outerRadius->excludeVaryingRanges(timeRanges); - innerRoundness->excludeVaryingRanges(timeRanges); - outerRoundness->excludeVaryingRanges(timeRanges); + points->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); + rotation->excludeVaryingRanges(timeRanges); + innerRadius->excludeVaryingRanges(timeRanges); + outerRadius->excludeVaryingRanges(timeRanges); + innerRoundness->excludeVaryingRanges(timeRanges); + outerRoundness->excludeVaryingRanges(timeRanges); } bool PolyStarElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(points != nullptr && position != nullptr && rotation != nullptr && - innerRadius != nullptr && outerRadius != nullptr && innerRoundness != nullptr && - outerRoundness != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(points != nullptr && position != nullptr && rotation != nullptr && + innerRadius != nullptr && outerRadius != nullptr && innerRoundness != nullptr && + outerRoundness != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/RectangleElement.cpp b/src/base/shapes/RectangleElement.cpp index e9c7ccb7ad..0322041e1c 100644 --- a/src/base/shapes/RectangleElement.cpp +++ b/src/base/shapes/RectangleElement.cpp @@ -21,22 +21,22 @@ namespace pag { RectangleElement::~RectangleElement() { - delete size; - delete position; - delete roundness; + delete size; + delete position; + delete roundness; } void RectangleElement::excludeVaryingRanges(std::vector* timeRanges) const { - position->excludeVaryingRanges(timeRanges); - size->excludeVaryingRanges(timeRanges); - roundness->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); + size->excludeVaryingRanges(timeRanges); + roundness->excludeVaryingRanges(timeRanges); } bool RectangleElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(position != nullptr && size != nullptr && roundness != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(position != nullptr && size != nullptr && roundness != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/RepeaterElement.cpp b/src/base/shapes/RepeaterElement.cpp index ff40fd0cb7..a4a63ec46a 100644 --- a/src/base/shapes/RepeaterElement.cpp +++ b/src/base/shapes/RepeaterElement.cpp @@ -21,22 +21,22 @@ namespace pag { RepeaterElement::~RepeaterElement() { - delete copies; - delete offset; - delete transform; + delete copies; + delete offset; + delete transform; } void RepeaterElement::excludeVaryingRanges(std::vector* timeRanges) const { - copies->excludeVaryingRanges(timeRanges); - offset->excludeVaryingRanges(timeRanges); - transform->excludeVaryingRanges(timeRanges); + copies->excludeVaryingRanges(timeRanges); + offset->excludeVaryingRanges(timeRanges); + transform->excludeVaryingRanges(timeRanges); } bool RepeaterElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(copies != nullptr && offset != nullptr && transform != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(copies != nullptr && offset != nullptr && transform != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/RepeaterTransform.cpp b/src/base/shapes/RepeaterTransform.cpp index 0d5c123d43..0c94170817 100644 --- a/src/base/shapes/RepeaterTransform.cpp +++ b/src/base/shapes/RepeaterTransform.cpp @@ -21,25 +21,25 @@ namespace pag { RepeaterTransform::~RepeaterTransform() { - delete anchorPoint; - delete position; - delete scale; - delete rotation; - delete startOpacity; - delete endOpacity; + delete anchorPoint; + delete position; + delete scale; + delete rotation; + delete startOpacity; + delete endOpacity; } void RepeaterTransform::excludeVaryingRanges(std::vector* timeRanges) const { - anchorPoint->excludeVaryingRanges(timeRanges); - position->excludeVaryingRanges(timeRanges); - scale->excludeVaryingRanges(timeRanges); - rotation->excludeVaryingRanges(timeRanges); - startOpacity->excludeVaryingRanges(timeRanges); - endOpacity->excludeVaryingRanges(timeRanges); + anchorPoint->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); + scale->excludeVaryingRanges(timeRanges); + rotation->excludeVaryingRanges(timeRanges); + startOpacity->excludeVaryingRanges(timeRanges); + endOpacity->excludeVaryingRanges(timeRanges); } bool RepeaterTransform::verify() const { - VerifyAndReturn(anchorPoint != nullptr && position != nullptr && scale != nullptr && - rotation != nullptr && startOpacity != nullptr && endOpacity != nullptr); + VerifyAndReturn(anchorPoint != nullptr && position != nullptr && scale != nullptr && + rotation != nullptr && startOpacity != nullptr && endOpacity != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/RoundCornersElement.cpp b/src/base/shapes/RoundCornersElement.cpp index 83011e4eeb..ead728e5e1 100644 --- a/src/base/shapes/RoundCornersElement.cpp +++ b/src/base/shapes/RoundCornersElement.cpp @@ -21,18 +21,18 @@ namespace pag { RoundCornersElement::~RoundCornersElement() { - delete radius; + delete radius; } void RoundCornersElement::excludeVaryingRanges(std::vector* timeRanges) const { - radius->excludeVaryingRanges(timeRanges); + radius->excludeVaryingRanges(timeRanges); } bool RoundCornersElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(radius != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(radius != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/ShapeGroupElement.cpp b/src/base/shapes/ShapeGroupElement.cpp index 27359821bd..6d9277229d 100644 --- a/src/base/shapes/ShapeGroupElement.cpp +++ b/src/base/shapes/ShapeGroupElement.cpp @@ -21,34 +21,34 @@ namespace pag { ShapeGroupElement::~ShapeGroupElement() { - delete transform; - for (auto& element : elements) { - delete element; - } + delete transform; + for (auto& element : elements) { + delete element; + } } void ShapeGroupElement::excludeVaryingRanges(std::vector* timeRanges) const { - transform->excludeVaryingRanges(timeRanges); - for (auto& element : elements) { - element->excludeVaryingRanges(timeRanges); - } + transform->excludeVaryingRanges(timeRanges); + for (auto& element : elements) { + element->excludeVaryingRanges(timeRanges); + } } bool ShapeGroupElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - if (transform == nullptr || !transform->verify()) { - VerifyFailed(); - return false; - } - for (auto& element : elements) { - if (element == nullptr || !element->verify()) { - VerifyFailed(); - return false; + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + if (transform == nullptr || !transform->verify()) { + VerifyFailed(); + return false; + } + for (auto& element : elements) { + if (element == nullptr || !element->verify()) { + VerifyFailed(); + return false; + } } - } - return true; + return true; } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/ShapePathElement.cpp b/src/base/shapes/ShapePathElement.cpp index 5c457ae8e0..d32a3763fd 100644 --- a/src/base/shapes/ShapePathElement.cpp +++ b/src/base/shapes/ShapePathElement.cpp @@ -21,18 +21,18 @@ namespace pag { ShapePathElement::~ShapePathElement() { - delete shapePath; + delete shapePath; } void ShapePathElement::excludeVaryingRanges(std::vector* timeRanges) const { - shapePath->excludeVaryingRanges(timeRanges); + shapePath->excludeVaryingRanges(timeRanges); } bool ShapePathElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(shapePath != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(shapePath != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/ShapeTransform.cpp b/src/base/shapes/ShapeTransform.cpp index f6e638eaad..7e2db32462 100644 --- a/src/base/shapes/ShapeTransform.cpp +++ b/src/base/shapes/ShapeTransform.cpp @@ -21,28 +21,28 @@ namespace pag { ShapeTransform::~ShapeTransform() { - delete anchorPoint; - delete position; - delete scale; - delete skew; - delete skewAxis; - delete rotation; - delete opacity; + delete anchorPoint; + delete position; + delete scale; + delete skew; + delete skewAxis; + delete rotation; + delete opacity; } void ShapeTransform::excludeVaryingRanges(std::vector* timeRanges) const { - anchorPoint->excludeVaryingRanges(timeRanges); - position->excludeVaryingRanges(timeRanges); - scale->excludeVaryingRanges(timeRanges); - skew->excludeVaryingRanges(timeRanges); - skewAxis->excludeVaryingRanges(timeRanges); - rotation->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); + anchorPoint->excludeVaryingRanges(timeRanges); + position->excludeVaryingRanges(timeRanges); + scale->excludeVaryingRanges(timeRanges); + skew->excludeVaryingRanges(timeRanges); + skewAxis->excludeVaryingRanges(timeRanges); + rotation->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); } bool ShapeTransform::verify() const { - VerifyAndReturn(anchorPoint != nullptr && position != nullptr && scale != nullptr && - skew != nullptr && skewAxis != nullptr && rotation != nullptr && - opacity != nullptr); + VerifyAndReturn(anchorPoint != nullptr && position != nullptr && scale != nullptr && + skew != nullptr && skewAxis != nullptr && rotation != nullptr && + opacity != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/StrokeElement.cpp b/src/base/shapes/StrokeElement.cpp index 3a1cdd4884..5b6cdf58e3 100644 --- a/src/base/shapes/StrokeElement.cpp +++ b/src/base/shapes/StrokeElement.cpp @@ -21,41 +21,41 @@ namespace pag { StrokeElement::~StrokeElement() { - delete miterLimit; - delete color; - delete opacity; - delete strokeWidth; - delete dashOffset; - for (auto& dash : dashes) { - delete dash; - } + delete miterLimit; + delete color; + delete opacity; + delete strokeWidth; + delete dashOffset; + for (auto& dash : dashes) { + delete dash; + } } void StrokeElement::excludeVaryingRanges(std::vector* timeRanges) const { - miterLimit->excludeVaryingRanges(timeRanges); - color->excludeVaryingRanges(timeRanges); - opacity->excludeVaryingRanges(timeRanges); - strokeWidth->excludeVaryingRanges(timeRanges); - if (!dashes.empty()) { - dashOffset->excludeVaryingRanges(timeRanges); - for (auto& property : dashes) { - property->excludeVaryingRanges(timeRanges); + miterLimit->excludeVaryingRanges(timeRanges); + color->excludeVaryingRanges(timeRanges); + opacity->excludeVaryingRanges(timeRanges); + strokeWidth->excludeVaryingRanges(timeRanges); + if (!dashes.empty()) { + dashOffset->excludeVaryingRanges(timeRanges); + for (auto& property : dashes) { + property->excludeVaryingRanges(timeRanges); + } } - } } bool StrokeElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - for (auto dash : dashes) { - if (dash == nullptr) { - VerifyFailed(); - return false; + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + for (auto dash : dashes) { + if (dash == nullptr) { + VerifyFailed(); + return false; + } } - } - VerifyAndReturn(miterLimit != nullptr && color != nullptr && opacity != nullptr && - strokeWidth != nullptr); + VerifyAndReturn(miterLimit != nullptr && color != nullptr && opacity != nullptr && + strokeWidth != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/shapes/TrimPathsElement.cpp b/src/base/shapes/TrimPathsElement.cpp index 25c9cdd15e..a7b5a48f7e 100644 --- a/src/base/shapes/TrimPathsElement.cpp +++ b/src/base/shapes/TrimPathsElement.cpp @@ -21,22 +21,22 @@ namespace pag { TrimPathsElement::~TrimPathsElement() { - delete start; - delete end; - delete offset; + delete start; + delete end; + delete offset; } void TrimPathsElement::excludeVaryingRanges(std::vector* timeRanges) const { - start->excludeVaryingRanges(timeRanges); - end->excludeVaryingRanges(timeRanges); - offset->excludeVaryingRanges(timeRanges); + start->excludeVaryingRanges(timeRanges); + end->excludeVaryingRanges(timeRanges); + offset->excludeVaryingRanges(timeRanges); } bool TrimPathsElement::verify() const { - if (!ShapeElement::verify()) { - VerifyFailed(); - return false; - } - VerifyAndReturn(start != nullptr && end != nullptr && offset != nullptr); + if (!ShapeElement::verify()) { + VerifyFailed(); + return false; + } + VerifyAndReturn(start != nullptr && end != nullptr && offset != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/text/TextAnimator.cpp b/src/base/text/TextAnimator.cpp index 4857cbdc71..08375524e8 100644 --- a/src/base/text/TextAnimator.cpp +++ b/src/base/text/TextAnimator.cpp @@ -21,40 +21,40 @@ namespace pag { TextAnimator::~TextAnimator() { - for (auto& selector : selectors) { - delete selector; - } - delete colorProperties; - delete typographyProperties; + for (auto& selector : selectors) { + delete selector; + } + delete colorProperties; + delete typographyProperties; } void TextAnimator::excludeVaryingRanges(std::vector* timeRanges) const { - for (auto& selector : selectors) { - selector->excludeVaryingRanges(timeRanges); - } - if (colorProperties != nullptr) { - colorProperties->excludeVaryingRanges(timeRanges); - } - if (typographyProperties != nullptr) { - typographyProperties->excludeVaryingRanges(timeRanges); - } + for (auto& selector : selectors) { + selector->excludeVaryingRanges(timeRanges); + } + if (colorProperties != nullptr) { + colorProperties->excludeVaryingRanges(timeRanges); + } + if (typographyProperties != nullptr) { + typographyProperties->excludeVaryingRanges(timeRanges); + } } bool TextAnimator::verify() const { - for (auto& selector : selectors) { - if (selector == nullptr || !selector->verify()) { - VerifyFailed(); - return false; + for (auto& selector : selectors) { + if (selector == nullptr || !selector->verify()) { + VerifyFailed(); + return false; + } + } + if (colorProperties != nullptr && !colorProperties->verify()) { + VerifyFailed(); + return false; + } + if (typographyProperties != nullptr && !typographyProperties->verify()) { + VerifyFailed(); + return false; } - } - if (colorProperties != nullptr && !colorProperties->verify()) { - VerifyFailed(); - return false; - } - if (typographyProperties != nullptr && !typographyProperties->verify()) { - VerifyFailed(); - return false; - } - return true; + return true; } } // namespace pag diff --git a/src/base/text/TextAnimatorColorProperties.cpp b/src/base/text/TextAnimatorColorProperties.cpp index 0e63527dae..2a83cb4019 100644 --- a/src/base/text/TextAnimatorColorProperties.cpp +++ b/src/base/text/TextAnimatorColorProperties.cpp @@ -21,20 +21,20 @@ namespace pag { TextAnimatorColorProperties::~TextAnimatorColorProperties() { - delete fillColor; - delete strokeColor; + delete fillColor; + delete strokeColor; } void TextAnimatorColorProperties::excludeVaryingRanges(std::vector* timeRanges) const { - if (fillColor != nullptr) { - fillColor->excludeVaryingRanges(timeRanges); - } - if (strokeColor != nullptr) { - strokeColor->excludeVaryingRanges(timeRanges); - } + if (fillColor != nullptr) { + fillColor->excludeVaryingRanges(timeRanges); + } + if (strokeColor != nullptr) { + strokeColor->excludeVaryingRanges(timeRanges); + } } bool TextAnimatorColorProperties::verify() const { - VerifyAndReturn(fillColor != nullptr || strokeColor != nullptr); + VerifyAndReturn(fillColor != nullptr || strokeColor != nullptr); } } // namespace pag diff --git a/src/base/text/TextAnimatorTypographyProperties.cpp b/src/base/text/TextAnimatorTypographyProperties.cpp index 6df58bfdf9..04d2f63099 100644 --- a/src/base/text/TextAnimatorTypographyProperties.cpp +++ b/src/base/text/TextAnimatorTypographyProperties.cpp @@ -21,39 +21,39 @@ namespace pag { TextAnimatorTypographyProperties::~TextAnimatorTypographyProperties() { - delete trackingType; - delete trackingAmount; - delete position; - delete scale; - delete rotation; - delete opacity; + delete trackingType; + delete trackingAmount; + delete position; + delete scale; + delete rotation; + delete opacity; } void TextAnimatorTypographyProperties::excludeVaryingRanges( std::vector* timeRanges) const { - if (trackingType != nullptr) { - trackingType->excludeVaryingRanges(timeRanges); - } - if (trackingAmount != nullptr) { - trackingAmount->excludeVaryingRanges(timeRanges); - } - if (position != nullptr) { - position->excludeVaryingRanges(timeRanges); - } - if (scale != nullptr) { - scale->excludeVaryingRanges(timeRanges); - } - if (rotation != nullptr) { - rotation->excludeVaryingRanges(timeRanges); - } - if (opacity != nullptr) { - opacity->excludeVaryingRanges(timeRanges); - } + if (trackingType != nullptr) { + trackingType->excludeVaryingRanges(timeRanges); + } + if (trackingAmount != nullptr) { + trackingAmount->excludeVaryingRanges(timeRanges); + } + if (position != nullptr) { + position->excludeVaryingRanges(timeRanges); + } + if (scale != nullptr) { + scale->excludeVaryingRanges(timeRanges); + } + if (rotation != nullptr) { + rotation->excludeVaryingRanges(timeRanges); + } + if (opacity != nullptr) { + opacity->excludeVaryingRanges(timeRanges); + } } bool TextAnimatorTypographyProperties::verify() const { - // trackingAmount is required,but trackingType could be empty. - VerifyAndReturn(trackingAmount != nullptr || position != nullptr || scale != nullptr || - rotation != nullptr || opacity != nullptr); + // trackingAmount is required,but trackingType could be empty. + VerifyAndReturn(trackingAmount != nullptr || position != nullptr || scale != nullptr || + rotation != nullptr || opacity != nullptr); } } // namespace pag diff --git a/src/base/text/TextMoreOptions.cpp b/src/base/text/TextMoreOptions.cpp index 286fb9c74a..12516844c2 100644 --- a/src/base/text/TextMoreOptions.cpp +++ b/src/base/text/TextMoreOptions.cpp @@ -21,14 +21,14 @@ namespace pag { TextMoreOptions::~TextMoreOptions() { - delete groupingAlignment; + delete groupingAlignment; } void TextMoreOptions::excludeVaryingRanges(std::vector* timeRanges) const { - groupingAlignment->excludeVaryingRanges(timeRanges); + groupingAlignment->excludeVaryingRanges(timeRanges); } bool TextMoreOptions::verify() const { - VerifyAndReturn(groupingAlignment != nullptr); + VerifyAndReturn(groupingAlignment != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/text/TextPathOptions.cpp b/src/base/text/TextPathOptions.cpp index 158517b789..506c8cf90f 100644 --- a/src/base/text/TextPathOptions.cpp +++ b/src/base/text/TextPathOptions.cpp @@ -21,23 +21,23 @@ namespace pag { TextPathOptions::~TextPathOptions() { - delete reversedPath; - delete perpendicularToPath; - delete forceAlignment; - delete firstMargin; - delete lastMargin; + delete reversedPath; + delete perpendicularToPath; + delete forceAlignment; + delete firstMargin; + delete lastMargin; } void TextPathOptions::excludeVaryingRanges(std::vector* timeRanges) const { - reversedPath->excludeVaryingRanges(timeRanges); - perpendicularToPath->excludeVaryingRanges(timeRanges); - forceAlignment->excludeVaryingRanges(timeRanges); - firstMargin->excludeVaryingRanges(timeRanges); - lastMargin->excludeVaryingRanges(timeRanges); + reversedPath->excludeVaryingRanges(timeRanges); + perpendicularToPath->excludeVaryingRanges(timeRanges); + forceAlignment->excludeVaryingRanges(timeRanges); + firstMargin->excludeVaryingRanges(timeRanges); + lastMargin->excludeVaryingRanges(timeRanges); } bool TextPathOptions::verify() const { - VerifyAndReturn(reversedPath != nullptr && perpendicularToPath != nullptr && - forceAlignment != nullptr && firstMargin != nullptr && lastMargin != nullptr); + VerifyAndReturn(reversedPath != nullptr && perpendicularToPath != nullptr && + forceAlignment != nullptr && firstMargin != nullptr && lastMargin != nullptr); } } // namespace pag \ No newline at end of file diff --git a/src/base/text/TextRangeSelector.cpp b/src/base/text/TextRangeSelector.cpp index f8e5bc11b3..2a0a95dac4 100644 --- a/src/base/text/TextRangeSelector.cpp +++ b/src/base/text/TextRangeSelector.cpp @@ -21,34 +21,34 @@ namespace pag { TextRangeSelector::~TextRangeSelector() { - delete start; - delete end; - delete offset; - delete mode; - delete amount; - delete smoothness; - delete easeHigh; - delete easeLow; - delete randomSeed; + delete start; + delete end; + delete offset; + delete mode; + delete amount; + delete smoothness; + delete easeHigh; + delete easeLow; + delete randomSeed; } void TextRangeSelector::excludeVaryingRanges(std::vector* timeRanges) const { - start->excludeVaryingRanges(timeRanges); - end->excludeVaryingRanges(timeRanges); - offset->excludeVaryingRanges(timeRanges); - mode->excludeVaryingRanges(timeRanges); - amount->excludeVaryingRanges(timeRanges); - smoothness->excludeVaryingRanges(timeRanges); - easeHigh->excludeVaryingRanges(timeRanges); - easeLow->excludeVaryingRanges(timeRanges); - if (randomizeOrder) { - randomSeed->excludeVaryingRanges(timeRanges); - } + start->excludeVaryingRanges(timeRanges); + end->excludeVaryingRanges(timeRanges); + offset->excludeVaryingRanges(timeRanges); + mode->excludeVaryingRanges(timeRanges); + amount->excludeVaryingRanges(timeRanges); + smoothness->excludeVaryingRanges(timeRanges); + easeHigh->excludeVaryingRanges(timeRanges); + easeLow->excludeVaryingRanges(timeRanges); + if (randomizeOrder) { + randomSeed->excludeVaryingRanges(timeRanges); + } } bool TextRangeSelector::verify() const { - VerifyAndReturn(start != nullptr && end != nullptr && offset != nullptr && mode != nullptr && - amount != nullptr && smoothness != nullptr && easeHigh != nullptr && - easeLow != nullptr && randomSeed != nullptr); + VerifyAndReturn(start != nullptr && end != nullptr && offset != nullptr && mode != nullptr && + amount != nullptr && smoothness != nullptr && easeHigh != nullptr && + easeLow != nullptr && randomSeed != nullptr); } } // namespace pag diff --git a/src/base/text/TextWigglySelector.cpp b/src/base/text/TextWigglySelector.cpp index b9d737dd7d..bb878db95f 100644 --- a/src/base/text/TextWigglySelector.cpp +++ b/src/base/text/TextWigglySelector.cpp @@ -21,26 +21,26 @@ namespace pag { TextWigglySelector::~TextWigglySelector() { - delete mode; - delete maxAmount; - delete minAmount; - delete wigglesPerSecond; - delete correlation; - delete temporalPhase; - delete spatialPhase; - delete lockDimensions; - delete randomSeed; + delete mode; + delete maxAmount; + delete minAmount; + delete wigglesPerSecond; + delete correlation; + delete temporalPhase; + delete spatialPhase; + delete lockDimensions; + delete randomSeed; } void TextWigglySelector::excludeVaryingRanges(std::vector* timeRanges) const { - // there are no static time ranges for TextWigglySelector - timeRanges->erase(timeRanges->begin(), timeRanges->end()); + // there are no static time ranges for TextWigglySelector + timeRanges->erase(timeRanges->begin(), timeRanges->end()); } bool TextWigglySelector::verify() const { - VerifyAndReturn(mode != nullptr && maxAmount != nullptr && minAmount != nullptr && - wigglesPerSecond != nullptr && correlation != nullptr && - temporalPhase != nullptr && spatialPhase != nullptr && - lockDimensions != nullptr && randomSeed != nullptr); + VerifyAndReturn(mode != nullptr && maxAmount != nullptr && minAmount != nullptr && + wigglesPerSecond != nullptr && correlation != nullptr && + temporalPhase != nullptr && spatialPhase != nullptr && + lockDimensions != nullptr && randomSeed != nullptr); } } // namespace pag diff --git a/src/base/utils/BezierEasing.cpp b/src/base/utils/BezierEasing.cpp index 08b3724671..0eafff9146 100644 --- a/src/base/utils/BezierEasing.cpp +++ b/src/base/utils/BezierEasing.cpp @@ -20,16 +20,16 @@ namespace pag { BezierEasing::BezierEasing(const Point& control1, const Point& control2) { - bezierPath = BezierPath::Build(Point::Zero(), control1, control2, Point::Make(1, 1), 0.005f); + bezierPath = BezierPath::Build(Point::Zero(), control1, control2, Point::Make(1, 1), 0.005f); } float BezierEasing::getInterpolation(float input) { - if (input <= 0) { - return 0; - } - if (input >= 1) { - return 1; - } - return bezierPath->getY(input); + if (input <= 0) { + return 0; + } + if (input >= 1) { + return 1; + } + return bezierPath->getY(input); } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/BezierEasing.h b/src/base/utils/BezierEasing.h index 44a9d5c114..9bb6579c85 100644 --- a/src/base/utils/BezierEasing.h +++ b/src/base/utils/BezierEasing.h @@ -23,21 +23,21 @@ namespace pag { class BezierEasing : public Interpolator { - public: - BezierEasing(const Point& control1, const Point& control2); +public: + BezierEasing(const Point& control1, const Point& control2); - /** - * Maps a value representing the elapsed fraction of an animation to a value that represents the - * interpolated fraction. This interpolated value is then multiplied by the change in value of an - * animation to derive the animated value at the current elapsed animation time. - * @param input input A value between 0 and 1.0 indicating our current point in the animation - * where 0 represents the start and 1.0 represents the end. - * @return The interpolation value. This value can be more than 1.0 for interpolators which - * overshoot their targets, or less than 0 for interpolators that undershoot their targets. - */ - float getInterpolation(float input) override; + /** + * Maps a value representing the elapsed fraction of an animation to a value that represents the + * interpolated fraction. This interpolated value is then multiplied by the change in value of an + * animation to derive the animated value at the current elapsed animation time. + * @param input input A value between 0 and 1.0 indicating our current point in the animation + * where 0 represents the start and 1.0 represents the end. + * @return The interpolation value. This value can be more than 1.0 for interpolators which + * overshoot their targets, or less than 0 for interpolators that undershoot their targets. + */ + float getInterpolation(float input) override; - private: - std::shared_ptr bezierPath = nullptr; +private: + std::shared_ptr bezierPath = nullptr; }; } // namespace pag diff --git a/src/base/utils/BezierPath.cpp b/src/base/utils/BezierPath.cpp index 334fe0a79b..4908a9ab51 100644 --- a/src/base/utils/BezierPath.cpp +++ b/src/base/utils/BezierPath.cpp @@ -25,38 +25,38 @@ namespace pag { #define MaxBezierTValue 0x3FFFFFFF bool TSpanBigEnough(int tSpan) { - return (tSpan >> 10) != 0; + return (tSpan >> 10) != 0; } float ClampTo(float value, float min, float max) { - if (value < min) { - value = min; - } - if (value > max) { - value = max; - } - return value; + if (value < min) { + value = min; + } + if (value > max) { + value = max; + } + return value; } float MaxFloat(float a, float b) { - return a > b ? a : b; + return a > b ? a : b; } float MinFloat(float a, float b) { - return a < b ? a : b; + return a < b ? a : b; } float Distance(const Point& a, const Point& b) { - auto dx = a.x - b.x; - auto dy = a.y - b.y; - return sqrtf(dx * dx + dy * dy); + auto dx = a.x - b.x; + auto dy = a.y - b.y; + return sqrtf(dx * dx + dy * dy); } bool PointOnLine(const Point& point1, const Point& point2, const Point& point3, const float& precision) { - auto distance = point1.x * point2.y + point1.y * point3.x + point2.x * point3.y - - point3.x * point2.y - point3.y * point1.x - point2.x * point1.y; - return fabs(distance) < precision; + auto distance = point1.x * point2.y + point1.y * point3.x + point2.x * point3.y - + point3.x * point2.y - point3.y * point1.x - point2.x * point1.y; + return fabs(distance) < precision; } /** @@ -64,213 +64,213 @@ bool PointOnLine(const Point& point1, const Point& point2, const Point& point3, * two new cubics in result: result[0..3] and result[3..6] */ void SplitCubicCurveAt(const Point points[4], Point result[7], float t) { - auto p1 = Interpolate(points[0], points[1], t); - auto bc = Interpolate(points[1], points[2], t); - auto p5 = Interpolate(points[2], points[3], t); - auto p2 = Interpolate(p1, bc, t); - auto p4 = Interpolate(bc, p5, t); + auto p1 = Interpolate(points[0], points[1], t); + auto bc = Interpolate(points[1], points[2], t); + auto p5 = Interpolate(points[2], points[3], t); + auto p2 = Interpolate(p1, bc, t); + auto p4 = Interpolate(bc, p5, t); - result[0] = points[0]; - result[1] = p1; - result[2] = p2; - result[3] = Interpolate(p2, p4, t); - result[4] = p4; - result[5] = p5; - result[6] = points[3]; + result[0] = points[0]; + result[1] = p1; + result[2] = p2; + result[3] = Interpolate(p2, p4, t); + result[4] = p4; + result[5] = p5; + result[6] = points[3]; } bool DistanceExceedsLimit(const Point& pt1, const Point& pt2, const float& precision) { - return MaxFloat(fabsf(pt2.x - pt1.x), fabsf(pt2.y - pt1.y)) > precision; + return MaxFloat(fabsf(pt2.x - pt1.x), fabsf(pt2.y - pt1.y)) > precision; } bool CubicTooCurvy(const Point pts[4], const float& precision) { - static float oneOfThird = 1.0f / 3; - static float twoOfThird = 2.0f / 3; - auto pt1 = Interpolate(pts[0], pts[3], oneOfThird); - auto pt2 = Interpolate(pts[0], pts[3], twoOfThird); - return DistanceExceedsLimit(pts[1], pt1, precision) || - DistanceExceedsLimit(pts[2], pt2, precision); + static float oneOfThird = 1.0f / 3; + static float twoOfThird = 2.0f / 3; + auto pt1 = Interpolate(pts[0], pts[3], oneOfThird); + auto pt2 = Interpolate(pts[0], pts[3], twoOfThird); + return DistanceExceedsLimit(pts[1], pt1, precision) || + DistanceExceedsLimit(pts[2], pt2, precision); } float BuildCubicSegments(const Point points[4], float distance, unsigned minT, unsigned maxT, std::vector& segments, const float& precision) { - if (TSpanBigEnough(maxT - minT) && CubicTooCurvy(points, precision)) { - auto halfT = (minT + maxT) >> 1; - Point result[7]; - SplitCubicCurveAt(points, result, 0.5f); - distance = BuildCubicSegments(result, distance, minT, halfT, segments, precision); - distance = BuildCubicSegments(&result[3], distance, halfT, maxT, segments, precision); - } else { - distance += Distance(points[0], points[3]); - BezierSegment segment = {points[3], distance, maxT}; - segments.push_back(segment); - } - return distance; + if (TSpanBigEnough(maxT - minT) && CubicTooCurvy(points, precision)) { + auto halfT = (minT + maxT) >> 1; + Point result[7]; + SplitCubicCurveAt(points, result, 0.5f); + distance = BuildCubicSegments(result, distance, minT, halfT, segments, precision); + distance = BuildCubicSegments(&result[3], distance, halfT, maxT, segments, precision); + } else { + distance += Distance(points[0], points[3]); + BezierSegment segment = {points[3], distance, maxT}; + segments.push_back(segment); + } + return distance; } BezierKey BezierKey::Make(const Point points[4], float precision) { - BezierKey bezierKey = {}; - auto values = reinterpret_cast(points); - for (int i = 0; i < 8; i++) { - bezierKey.values[i] = static_cast(roundf(values[i] / precision)); - } - bezierKey.values[8] = static_cast(roundf(1 / precision)); - return bezierKey; + BezierKey bezierKey = {}; + auto values = reinterpret_cast(points); + for (int i = 0; i < 8; i++) { + bezierKey.values[i] = static_cast(roundf(values[i] / precision)); + } + bezierKey.values[8] = static_cast(roundf(1 / precision)); + return bezierKey; } bool BezierKey::operator==(const pag::BezierKey& other) const { - for (int i = 0; i < 9; i++) { - if (values[i] != other.values[i]) { - return false; + for (int i = 0; i < 9; i++) { + if (values[i] != other.values[i]) { + return false; + } } - } - return true; + return true; } size_t BezierHasher::operator()(const pag::BezierKey& key) const { - size_t hash = 0; - auto& values = key.values; - for (int i = 0; i < 9; i++) { - hash ^= values[i] + 0x9e3779b9 + (hash << 6) + (hash >> 2); - } - return hash; + size_t hash = 0; + auto& values = key.values; + for (int i = 0; i < 9; i++) { + hash ^= values[i] + 0x9e3779b9 + (hash << 6) + (hash >> 2); + } + return hash; } static std::unordered_map, BezierHasher> BezierCacheMap = - std::unordered_map, BezierHasher>{}; + std::unordered_map, BezierHasher> {}; static std::mutex locker = {}; std::shared_ptr BezierPath::Build(const pag::Point& start, const pag::Point& control1, - const pag::Point& control2, const pag::Point& end, - float precision) { - Point points[] = {start, control1, control2, end}; - auto bezierKey = BezierKey::Make(points, precision); - { - std::lock_guard autoLock(locker); - auto result = BezierCacheMap.find(bezierKey); - if (result != BezierCacheMap.end()) { - auto& weak = result->second; - auto data = weak.lock(); - if (data) { - return data; - } - BezierCacheMap.erase(result); + const pag::Point& control2, const pag::Point& end, + float precision) { + Point points[] = {start, control1, control2, end}; + auto bezierKey = BezierKey::Make(points, precision); + { + std::lock_guard autoLock(locker); + auto result = BezierCacheMap.find(bezierKey); + if (result != BezierCacheMap.end()) { + auto& weak = result->second; + auto data = weak.lock(); + if (data) { + return data; + } + BezierCacheMap.erase(result); + } } - } - auto bezierPath = std::shared_ptr(new BezierPath()); - BezierSegment segment = {points[0], 0, 0}; - bezierPath->segments.push_back(segment); - if (PointOnLine(points[0], points[3], points[1], precision) && - PointOnLine(points[0], points[3], points[2], precision)) { - bezierPath->length = Distance(points[0], points[3]); - segment = {points[3], bezierPath->length, MaxBezierTValue}; + auto bezierPath = std::shared_ptr(new BezierPath()); + BezierSegment segment = {points[0], 0, 0}; bezierPath->segments.push_back(segment); - } else { - bezierPath->length = - BuildCubicSegments(points, 0, 0, MaxBezierTValue, bezierPath->segments, precision); - } - { - std::lock_guard autoLock(locker); - std::weak_ptr weak = bezierPath; - BezierCacheMap.insert(std::make_pair(bezierKey, std::move(weak))); - } - return bezierPath; + if (PointOnLine(points[0], points[3], points[1], precision) && + PointOnLine(points[0], points[3], points[2], precision)) { + bezierPath->length = Distance(points[0], points[3]); + segment = {points[3], bezierPath->length, MaxBezierTValue}; + bezierPath->segments.push_back(segment); + } else { + bezierPath->length = + BuildCubicSegments(points, 0, 0, MaxBezierTValue, bezierPath->segments, precision); + } + { + std::lock_guard autoLock(locker); + std::weak_ptr weak = bezierPath; + BezierCacheMap.insert(std::make_pair(bezierKey, std::move(weak))); + } + return bezierPath; } Point BezierPath::getPosition(float percent) const { - if (percent <= 0) { - return segments[0].position; - } - if (percent >= 1) { - return segments.back().position; - } - int startIndex, endIndex; - float fraction; - findSegmentAtDistance(length * percent, startIndex, endIndex, fraction); - return Interpolate(segments[startIndex].position, segments[endIndex].position, fraction); + if (percent <= 0) { + return segments[0].position; + } + if (percent >= 1) { + return segments.back().position; + } + int startIndex, endIndex; + float fraction; + findSegmentAtDistance(length * percent, startIndex, endIndex, fraction); + return Interpolate(segments[startIndex].position, segments[endIndex].position, fraction); } float BezierPath::getT(float percent) const { - if (percent <= 0) { - return 0; - } - if (percent >= 1) { - return 1; - } - int startIndex, endIndex; - float fraction; - findSegmentAtDistance(length * percent, startIndex, endIndex, fraction); - return Interpolate(segments[startIndex].tValue, segments[endIndex].tValue, fraction) / - static_cast(MaxBezierTValue); + if (percent <= 0) { + return 0; + } + if (percent >= 1) { + return 1; + } + int startIndex, endIndex; + float fraction; + findSegmentAtDistance(length * percent, startIndex, endIndex, fraction); + return Interpolate(segments[startIndex].tValue, segments[endIndex].tValue, fraction) / + static_cast(MaxBezierTValue); } float BezierPath::getY(float x) const { - int startIndex = 0; - auto endIndex = static_cast(segments.size() - 1); - while (endIndex - startIndex > 1) { - auto middleIndex = (startIndex + endIndex) >> 1; - if (x < segments[middleIndex].position.x) { - endIndex = middleIndex; - } else { - startIndex = middleIndex; + int startIndex = 0; + auto endIndex = static_cast(segments.size() - 1); + while (endIndex - startIndex > 1) { + auto middleIndex = (startIndex + endIndex) >> 1; + if (x < segments[middleIndex].position.x) { + endIndex = middleIndex; + } else { + startIndex = middleIndex; + } } - } - auto& start = segments[startIndex].position; - auto& end = segments[endIndex].position; - auto xRange = end.x - start.x; - if (xRange == 0) { - return start.y; - } - auto fraction = (x - start.x) / xRange; - return Interpolate(start.y, end.y, fraction); + auto& start = segments[startIndex].position; + auto& end = segments[endIndex].position; + auto xRange = end.x - start.x; + if (xRange == 0) { + return start.y; + } + auto fraction = (x - start.x) / xRange; + return Interpolate(start.y, end.y, fraction); } float BezierPath::getX(float y) const { - int startIndex = 0; - auto endIndex = static_cast(segments.size() - 1); - while (endIndex - startIndex > 1) { - auto middleIndex = (startIndex + endIndex) >> 1; - if (y < segments[middleIndex].position.y) { - endIndex = middleIndex; - } else { - startIndex = middleIndex; + int startIndex = 0; + auto endIndex = static_cast(segments.size() - 1); + while (endIndex - startIndex > 1) { + auto middleIndex = (startIndex + endIndex) >> 1; + if (y < segments[middleIndex].position.y) { + endIndex = middleIndex; + } else { + startIndex = middleIndex; + } } - } - auto& start = segments[startIndex].position; - auto& end = segments[endIndex].position; - auto yRange = end.y - start.y; - if (yRange == 0) { - return start.x; - } - auto fraction = (y - start.y) / yRange; - return Interpolate(start.x, end.x, fraction); + auto& start = segments[startIndex].position; + auto& end = segments[endIndex].position; + auto yRange = end.y - start.y; + if (yRange == 0) { + return start.x; + } + auto fraction = (y - start.y) / yRange; + return Interpolate(start.x, end.x, fraction); } float BezierPath::getLength() const { - return length; + return length; } void BezierPath::findSegmentAtDistance(float distance, int& startIndex, int& endIndex, float& fraction) const { - startIndex = 0; - endIndex = static_cast(segments.size() - 1); - while (endIndex - startIndex > 1) { - auto middleIndex = (startIndex + endIndex) >> 1; - if (distance < segments[middleIndex].distance) { - endIndex = middleIndex; + startIndex = 0; + endIndex = static_cast(segments.size() - 1); + while (endIndex - startIndex > 1) { + auto middleIndex = (startIndex + endIndex) >> 1; + if (distance < segments[middleIndex].distance) { + endIndex = middleIndex; + } else { + startIndex = middleIndex; + } + } + auto& start = segments[startIndex]; + auto& end = segments[endIndex]; + auto distanceRange = end.distance - start.distance; + if (distanceRange == 0) { + fraction = 0; } else { - startIndex = middleIndex; + fraction = (distance - start.distance) / distanceRange; } - } - auto& start = segments[startIndex]; - auto& end = segments[endIndex]; - auto distanceRange = end.distance - start.distance; - if (distanceRange == 0) { - fraction = 0; - } else { - fraction = (distance - start.distance) / distanceRange; - } } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/BezierPath.h b/src/base/utils/BezierPath.h index cd245d03ab..287bd64728 100644 --- a/src/base/utils/BezierPath.h +++ b/src/base/utils/BezierPath.h @@ -24,70 +24,70 @@ namespace pag { struct BezierKey { - int32_t values[9]; + int32_t values[9]; - static BezierKey Make(const Point points[4], float precision); + static BezierKey Make(const Point points[4], float precision); - bool operator==(const BezierKey& other) const; + bool operator==(const BezierKey& other) const; }; struct BezierHasher { - size_t operator()(const BezierKey& key) const; + size_t operator()(const BezierKey& key) const; }; struct BezierSegment { - Point position; - /** - * Total distance up to this point - */ - float distance; - /** - * Total t value up to this point - */ - unsigned tValue; + Point position; + /** + * Total distance up to this point + */ + float distance; + /** + * Total t value up to this point + */ + unsigned tValue; }; class BezierPath { - public: - /** - * Creates a cubic bezier path. - */ - static std::shared_ptr Build(const Point& start, const Point& control1, - const Point& control2, const Point& end, - float precision); +public: + /** + * Creates a cubic bezier path. + */ + static std::shared_ptr Build(const Point& start, const Point& control1, + const Point& control2, const Point& end, + float precision); - /** - * Calculates a point on the curve, for a given value between 0 and 1.0 indicating the percent of - * the curve length where 0 represents the start and 1.0 represents the end. - */ - Point getPosition(float percent) const; + /** + * Calculates a point on the curve, for a given value between 0 and 1.0 indicating the percent of + * the curve length where 0 represents the start and 1.0 represents the end. + */ + Point getPosition(float percent) const; - /** - * Calculates a t value of the curve, for a given value between 0 and 1.0 indicating the percent - * of the curve length where 0 represents the start and 1.0 represents the end. - */ - float getT(float percent) const; + /** + * Calculates a t value of the curve, for a given value between 0 and 1.0 indicating the percent + * of the curve length where 0 represents the start and 1.0 represents the end. + */ + float getT(float percent) const; - /** - * Calculates a y point value on the curve, for a given x point value. - */ - float getY(float x) const; + /** + * Calculates a y point value on the curve, for a given x point value. + */ + float getY(float x) const; - /** - * Calculates a x point value on the curve, for a given y point value. - */ - float getX(float y) const; + /** + * Calculates a x point value on the curve, for a given y point value. + */ + float getX(float y) const; - /** - * Returns the length of the bezier path in pixels. - */ - float getLength() const; + /** + * Returns the length of the bezier path in pixels. + */ + float getLength() const; - private: - float length = 0; - std::vector segments; +private: + float length = 0; + std::vector segments; - BezierPath() = default; - void findSegmentAtDistance(float distance, int& startIndex, int& endIndex, float& fraction) const; + BezierPath() = default; + void findSegmentAtDistance(float distance, int& startIndex, int& endIndex, float& fraction) const; }; } // namespace pag diff --git a/src/base/utils/BytesKey.cpp b/src/base/utils/BytesKey.cpp index 4867f2f682..c32c547fa0 100644 --- a/src/base/utils/BytesKey.cpp +++ b/src/base/utils/BytesKey.cpp @@ -21,47 +21,47 @@ namespace pag { union DataConverter { - float floatValue; - uint8_t bytes[4]; - uint32_t uintValue; + float floatValue; + uint8_t bytes[4]; + uint32_t uintValue; }; union PointerConverter { - const void* pointer; - uint32_t uintValues[2]; + const void* pointer; + uint32_t uintValues[2]; }; void BytesKey::write(uint32_t value) { - values.push_back(value); + values.push_back(value); } void BytesKey::write(const void* value) { - PointerConverter converter = {}; - converter.pointer = value; - values.push_back(converter.uintValues[0]); - static size_t size = sizeof(intptr_t); - if (size > 4) { - values.push_back(converter.uintValues[1]); - } + PointerConverter converter = {}; + converter.pointer = value; + values.push_back(converter.uintValues[0]); + static size_t size = sizeof(intptr_t); + if (size > 4) { + values.push_back(converter.uintValues[1]); + } } void BytesKey::write(const uint8_t value[4]) { - DataConverter converter = {}; - memcpy(converter.bytes, value, 4); - values.push_back(converter.uintValue); + DataConverter converter = {}; + memcpy(converter.bytes, value, 4); + values.push_back(converter.uintValue); } void BytesKey::write(float value) { - DataConverter converter = {}; - converter.floatValue = value; - values.push_back(converter.uintValue); + DataConverter converter = {}; + converter.floatValue = value; + values.push_back(converter.uintValue); } size_t BytesHasher::operator()(const BytesKey& key) const { - auto hash = key.values.size(); - for (auto& value : key.values) { - hash ^= value + 0x9e3779b9 + (hash << 6u) + (hash >> 2u); - } - return hash; + auto hash = key.values.size(); + for (auto& value : key.values) { + hash ^= value + 0x9e3779b9 + (hash << 6u) + (hash >> 2u); + } + return hash; } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/BytesKey.h b/src/base/utils/BytesKey.h index 48bd2fee55..d3f02e63b0 100644 --- a/src/base/utils/BytesKey.h +++ b/src/base/utils/BytesKey.h @@ -26,52 +26,52 @@ namespace pag { * A key used for hashing a byte stream. */ class BytesKey { - public: - /** - * Returns true if this key is invalid. - */ - bool isValid() const { - return !values.empty(); - } +public: + /** + * Returns true if this key is invalid. + */ + bool isValid() const { + return !values.empty(); + } - /** - * Writes a uint32 value into the key. - */ - void write(uint32_t value); + /** + * Writes a uint32 value into the key. + */ + void write(uint32_t value); - /** - * Writes a pointer value into the key. - */ - void write(const void* value); + /** + * Writes a pointer value into the key. + */ + void write(const void* value); - /** - * Writes a uint32 value into the key. - */ - void write(const uint8_t value[4]); + /** + * Writes a uint32 value into the key. + */ + void write(const uint8_t value[4]); - /** - * Writes a float value into the key. - */ - void write(float value); + /** + * Writes a float value into the key. + */ + void write(float value); - friend bool operator==(const BytesKey& a, const BytesKey& b) { - return a.values == b.values; - } + friend bool operator==(const BytesKey& a, const BytesKey& b) { + return a.values == b.values; + } - bool operator<(const BytesKey& key) const { - return values < key.values; - } + bool operator<(const BytesKey& key) const { + return values < key.values; + } - private: - std::vector values = {}; +private: + std::vector values = {}; - friend struct BytesHasher; + friend struct BytesHasher; }; /** * The hasher for BytesKey. */ struct BytesHasher { - size_t operator()(const BytesKey& key) const; + size_t operator()(const BytesKey& key) const; }; } // namespace pag diff --git a/src/base/utils/EnumClassHash.h b/src/base/utils/EnumClassHash.h index 8b5842b473..558b264a15 100644 --- a/src/base/utils/EnumClassHash.h +++ b/src/base/utils/EnumClassHash.h @@ -19,9 +19,9 @@ #pragma once namespace pag { struct EnumClassHash { - template - size_t operator()(T t) const { - return static_cast(t); - } + template + size_t operator()(T t) const { + return static_cast(t); + } }; } // namespace pag diff --git a/src/base/utils/GetTimer.cpp b/src/base/utils/GetTimer.cpp index 6191a4cd45..53371c848e 100644 --- a/src/base/utils/GetTimer.cpp +++ b/src/base/utils/GetTimer.cpp @@ -20,9 +20,9 @@ namespace pag { int64_t GetTimer() { - static auto START_TIME = std::chrono::high_resolution_clock::now(); - auto now = std::chrono::high_resolution_clock::now(); - auto ns = std::chrono::duration_cast(now - START_TIME); - return static_cast(ns.count() * 1e-3); + static auto START_TIME = std::chrono::high_resolution_clock::now(); + auto now = std::chrono::high_resolution_clock::now(); + auto ns = std::chrono::duration_cast(now - START_TIME); + return static_cast(ns.count() * 1e-3); } } // namespace pag diff --git a/src/base/utils/Interpolate.h b/src/base/utils/Interpolate.h index 865d8983cc..39bc4540be 100644 --- a/src/base/utils/Interpolate.h +++ b/src/base/utils/Interpolate.h @@ -26,60 +26,60 @@ inline T Interpolate(const T& a, const T& b, const float& t); template <> inline float Interpolate(const float& a, const float& b, const float& t) { - return a + (b - a) * t; + return a + (b - a) * t; } template <> inline uint8_t Interpolate(const uint8_t& a, const uint8_t& b, const float& t) { - auto ret = a + (b - a) * t; - return static_cast(ret > 255 ? 255 : (ret < 0 ? 0 : ret)); + auto ret = a + (b - a) * t; + return static_cast(ret > 255 ? 255 : (ret < 0 ? 0 : ret)); } template <> inline uint16_t Interpolate(const uint16_t& a, const uint16_t& b, const float& t) { - auto ret = a + (b - a) * t; - return static_cast(ret > 65535 ? 65535 : (ret < 0 ? 0 : ret)); + auto ret = a + (b - a) * t; + return static_cast(ret > 65535 ? 65535 : (ret < 0 ? 0 : ret)); } template <> inline Point Interpolate(const Point& a, const Point& b, const float& t) { - return {Interpolate(a.x, b.x, t), Interpolate(a.y, b.y, t)}; + return {Interpolate(a.x, b.x, t), Interpolate(a.y, b.y, t)}; } template <> inline Color Interpolate(const Color& a, const Color& b, const float& t) { - return {Interpolate(a.red, b.red, t), Interpolate(a.green, b.green, t), - Interpolate(a.blue, b.blue, t)}; + return {Interpolate(a.red, b.red, t), Interpolate(a.green, b.green, t), + Interpolate(a.blue, b.blue, t)}; } template <> inline int64_t Interpolate(const int64_t& a, const int64_t& b, const float& t) { - return static_cast(a + (b - a) * t); + return static_cast(a + (b - a) * t); } template <> inline uint32_t Interpolate(const uint32_t& a, const uint32_t& b, const float& t) { - return static_cast(a + (b - a) * t); + return static_cast(a + (b - a) * t); } template <> inline int32_t Interpolate(const int32_t& a, const int32_t& b, const float& t) { - return static_cast(a + (b - a) * t); + return static_cast(a + (b - a) * t); } template <> inline PathHandle Interpolate(const PathHandle& a, const PathHandle& b, const float& t) { - auto path = new PathData(); - a->interpolate(*(b.get()), path, t); - return PathHandle(path); + auto path = new PathData(); + a->interpolate(*(b.get()), path, t); + return PathHandle(path); } template <> inline GradientColorHandle Interpolate(const GradientColorHandle& a, const GradientColorHandle& b, const float& t) { - auto gradientColor = new GradientColor(); - a->interpolate(*(b.get()), gradientColor, t); - return GradientColorHandle(gradientColor); + auto gradientColor = new GradientColor(); + a->interpolate(*(b.get()), gradientColor, t); + return GradientColorHandle(gradientColor); } } // namespace pag diff --git a/src/base/utils/Interpolator.h b/src/base/utils/Interpolator.h index 87e760219d..5128b822cb 100644 --- a/src/base/utils/Interpolator.h +++ b/src/base/utils/Interpolator.h @@ -22,20 +22,20 @@ namespace pag { class Interpolator { - public: - virtual ~Interpolator() = default; +public: + virtual ~Interpolator() = default; - /** - * Maps a value representing the elapsed fraction of an animation to a value that represents the - * interpolated fraction. This interpolated value is then multiplied by the change in value of an - * animation to derive the animated value at the current elapsed animation time. - * @param input input A value between 0 and 1.0 indicating our current point in the animation - * where 0 represents the start and 1.0 represents the end. - * @return The interpolation value. This value can be more than 1.0 for interpolators which - * overshoot their targets, or less than 0 for interpolators that undershoot their targets. - */ - virtual float getInterpolation(float input) { - return input; - } + /** + * Maps a value representing the elapsed fraction of an animation to a value that represents the + * interpolated fraction. This interpolated value is then multiplied by the change in value of an + * animation to derive the animated value at the current elapsed animation time. + * @param input input A value between 0 and 1.0 indicating our current point in the animation + * where 0 represents the start and 1.0 represents the end. + * @return The interpolation value. This value can be more than 1.0 for interpolators which + * overshoot their targets, or less than 0 for interpolators that undershoot their targets. + */ + virtual float getInterpolation(float input) { + return input; + } }; } // namespace pag diff --git a/src/base/utils/MathExtra.h b/src/base/utils/MathExtra.h index dab868342d..9cc34a9ce5 100644 --- a/src/base/utils/MathExtra.h +++ b/src/base/utils/MathExtra.h @@ -30,28 +30,28 @@ static constexpr float FLOAT_SQRT2 = 1.41421356f; #define RadiansToDegrees(radians) ((radians) * (180.0f / M_PI_F)) static inline bool FloatNearlyZero(float x, float tolerance = FLOAT_NEARLY_ZERO) { - return fabsf(x) <= tolerance; + return fabsf(x) <= tolerance; } static inline bool FloatNearlyEqual(float x, float y, float tolerance = FLOAT_NEARLY_ZERO) { - return fabsf(x - y) <= tolerance; + return fabsf(x - y) <= tolerance; } static inline float SinSnapToZero(float radians) { - float v = sinf(radians); - return FloatNearlyZero(v) ? 0.0f : v; + float v = sinf(radians); + return FloatNearlyZero(v) ? 0.0f : v; } static inline float CosSnapToZero(float radians) { - float v = cosf(radians); - return FloatNearlyZero(v) ? 0.0f : v; + float v = cosf(radians); + return FloatNearlyZero(v) ? 0.0f : v; } static inline bool FloatsAreFinite(const float array[], int count) { - float prod = 0; - for (int i = 0; i < count; ++i) { - prod *= array[i]; - } - return prod == 0; + float prod = 0; + for (int i = 0; i < count; ++i) { + prod *= array[i]; + } + return prod == 0; } } // namespace pag diff --git a/src/base/utils/MatrixUtil.cpp b/src/base/utils/MatrixUtil.cpp index 53a103ac35..cbb04fbdf8 100644 --- a/src/base/utils/MatrixUtil.cpp +++ b/src/base/utils/MatrixUtil.cpp @@ -20,47 +20,47 @@ namespace pag { bool MapPointInverted(const Matrix& matrix, Point* point) { - Matrix inverted = {}; - bool canInvert = matrix.invert(&inverted); - if (canInvert) { - inverted.mapPoints(point, 1); - return true; - } - return false; + Matrix inverted = {}; + bool canInvert = matrix.invert(&inverted); + if (canInvert) { + inverted.mapPoints(point, 1); + return true; + } + return false; } float GetMaxScaleFactor(const Matrix& matrix) { - auto scale = GetScaleFactor(matrix); - return std::max(fabsf(scale.x), fabsf(scale.y)); + auto scale = GetScaleFactor(matrix); + return std::max(fabsf(scale.x), fabsf(scale.y)); } Point GetScaleFactor(const Matrix& matrix, float contentScale, bool inverted) { - Point scale = {}; - auto a = matrix.get(0); - auto c = matrix.get(1); - auto b = matrix.get(3); - auto d = matrix.get(4); - float determinant = a * d - b * c; - if (a == 1 && b == 0) { - scale.x = 1; - } else { - auto result = sqrtf(a * a + b * b); - scale.x = determinant < 0 ? -result : result; - } - if (c == 0 && d == 1) { - scale.y = 1; - } else { - auto result = sqrtf(c * c + d * d); - scale.y = determinant < 0 ? -result : result; - } - scale.x *= contentScale; - scale.y *= contentScale; + Point scale = {}; + auto a = matrix.get(0); + auto c = matrix.get(1); + auto b = matrix.get(3); + auto d = matrix.get(4); + float determinant = a * d - b * c; + if (a == 1 && b == 0) { + scale.x = 1; + } else { + auto result = sqrtf(a * a + b * b); + scale.x = determinant < 0 ? -result : result; + } + if (c == 0 && d == 1) { + scale.y = 1; + } else { + auto result = sqrtf(c * c + d * d); + scale.y = determinant < 0 ? -result : result; + } + scale.x *= contentScale; + scale.y *= contentScale; - if (inverted) { - scale.x = scale.x == 0 ? 0 : 1 / scale.x; - scale.y = scale.y == 0 ? 0 : 1 / scale.y; - } - return scale; + if (inverted) { + scale.x = scale.x == 0 ? 0 : 1 / scale.x; + scale.y = scale.y == 0 ? 0 : 1 / scale.y; + } + return scale; } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/Task.cpp b/src/base/utils/Task.cpp index 0c6fa9bb9a..0f721bf35c 100644 --- a/src/base/utils/Task.cpp +++ b/src/base/utils/Task.cpp @@ -30,146 +30,146 @@ namespace pag { int GetCPUCores() { - int cpuCores = 0; + int cpuCores = 0; #ifdef __APPLE__ - size_t len = sizeof(cpuCores); - // iOS 和 macOS 平台可以准确判断出 CPU 的物理核数。 - sysctlbyname("hw.physicalcpu", &cpuCores, &len, nullptr, 0); + size_t len = sizeof(cpuCores); + // iOS 和 macOS 平台可以准确判断出 CPU 的物理核数。 + sysctlbyname("hw.physicalcpu", &cpuCores, &len, nullptr, 0); #else - cpuCores = static_cast(std::thread::hardware_concurrency()); + cpuCores = static_cast(std::thread::hardware_concurrency()); #endif - if (cpuCores <= 0) { - cpuCores = 8; - } - return cpuCores; + if (cpuCores <= 0) { + cpuCores = 8; + } + return cpuCores; } std::shared_ptr Task::Make(std::unique_ptr executor) { - return std::shared_ptr(new Task(std::move(executor))); + return std::shared_ptr(new Task(std::move(executor))); } Task::Task(std::unique_ptr executor) : executor(std::move(executor)) { - taskGroup = TaskGroup::GetInstance(); + taskGroup = TaskGroup::GetInstance(); } Task::~Task() { - cancel(); + cancel(); } void Task::run() { - std::lock_guard autoLock(locker); - if (running) { - return; - } - running = true; - taskGroup->pushTask(this); + std::lock_guard autoLock(locker); + if (running) { + return; + } + running = true; + taskGroup->pushTask(this); } bool Task::isRunning() { - std::lock_guard autoLock(locker); - return running; + std::lock_guard autoLock(locker); + return running; } Executor* Task::wait() { - std::unique_lock autoLock(locker); - if (!running) { + std::unique_lock autoLock(locker); + if (!running) { + return executor.get(); + } + condition.wait(autoLock); return executor.get(); - } - condition.wait(autoLock); - return executor.get(); } void Task::cancel() { - std::unique_lock autoLock(locker); - if (!running) { - return; - } - if (taskGroup->removeTask(this)) { - running = false; - return; - } - condition.wait(autoLock); + std::unique_lock autoLock(locker); + if (!running) { + return; + } + if (taskGroup->removeTask(this)) { + running = false; + return; + } + condition.wait(autoLock); } void Task::execute() { - executor->execute(); - std::lock_guard auoLock(locker); - running = false; - condition.notify_all(); + executor->execute(); + std::lock_guard auoLock(locker); + running = false; + condition.notify_all(); } TaskGroup* TaskGroup::GetInstance() { - static TaskGroup taskGroup = {}; - return &taskGroup; + static TaskGroup taskGroup = {}; + return &taskGroup; } void TaskGroup::RunLoop(TaskGroup* taskGroup) { - while (true) { - auto task = taskGroup->popTask(); - if (!task) { - break; + while (true) { + auto task = taskGroup->popTask(); + if (!task) { + break; + } + task->execute(); } - task->execute(); - } } TaskGroup::TaskGroup() { - static const int CPUCores = GetCPUCores(); - auto maxThreads = CPUCores > 16 ? 16 : CPUCores; - activeThreads = maxThreads; - for (int i = 0; i < maxThreads; i++) { - threads.emplace_back(&TaskGroup::RunLoop, this); - } + static const int CPUCores = GetCPUCores(); + auto maxThreads = CPUCores > 16 ? 16 : CPUCores; + activeThreads = maxThreads; + for (int i = 0; i < maxThreads; i++) { + threads.emplace_back(&TaskGroup::RunLoop, this); + } } TaskGroup::~TaskGroup() { - exit(); - for (auto& thread : threads) { - if (thread.joinable()) { - thread.join(); + exit(); + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } } - } } void TaskGroup::pushTask(Task* task) { - std::lock_guard autoLock(locker); - tasks.push_back(task); - condition.notify_one(); + std::lock_guard autoLock(locker); + tasks.push_back(task); + condition.notify_one(); } Task* TaskGroup::popTask() { - std::unique_lock autoLock(locker); - activeThreads--; - while (true) { - if (tasks.empty()) { - condition.wait(autoLock); - if (exited) { - return nullptr; - } - } else { - auto task = tasks.front(); - tasks.pop_front(); - activeThreads++; - // LOGI("TaskGroup.activeThreads : %d", activeThreads); - return task; + std::unique_lock autoLock(locker); + activeThreads--; + while (true) { + if (tasks.empty()) { + condition.wait(autoLock); + if (exited) { + return nullptr; + } + } else { + auto task = tasks.front(); + tasks.pop_front(); + activeThreads++; + // LOGI("TaskGroup.activeThreads : %d", activeThreads); + return task; + } } - } } bool TaskGroup::removeTask(Task* task) { - std::lock_guard autoLock(locker); - auto position = std::find(tasks.begin(), tasks.end(), task); - if (position == tasks.end()) { - return false; - } - tasks.erase(position); - return true; + std::lock_guard autoLock(locker); + auto position = std::find(tasks.begin(), tasks.end(), task); + if (position == tasks.end()) { + return false; + } + tasks.erase(position); + return true; } void TaskGroup::exit() { - std::lock_guard autoLock(locker); - exited = true; - condition.notify_all(); + std::lock_guard autoLock(locker); + exited = true; + condition.notify_all(); } } // namespace pag diff --git a/src/base/utils/Task.h b/src/base/utils/Task.h index 29611f4d17..64cab8fd71 100644 --- a/src/base/utils/Task.h +++ b/src/base/utils/Task.h @@ -28,62 +28,62 @@ namespace pag { class Executor { - public: - virtual ~Executor() = default; +public: + virtual ~Executor() = default; - private: - virtual void execute() = 0; +private: + virtual void execute() = 0; - friend class Task; + friend class Task; }; class TaskGroup; class Task { - public: - static std::shared_ptr Make(std::unique_ptr executor); - ~Task(); - - void run(); - bool isRunning(); - Executor* wait(); - void cancel(); - - private: - std::mutex locker = {}; - std::condition_variable condition = {}; - bool running = false; - TaskGroup* taskGroup = nullptr; - std::unique_ptr executor = nullptr; - - explicit Task(std::unique_ptr executor); - void execute(); - - friend class TaskGroup; +public: + static std::shared_ptr Make(std::unique_ptr executor); + ~Task(); + + void run(); + bool isRunning(); + Executor* wait(); + void cancel(); + +private: + std::mutex locker = {}; + std::condition_variable condition = {}; + bool running = false; + TaskGroup* taskGroup = nullptr; + std::unique_ptr executor = nullptr; + + explicit Task(std::unique_ptr executor); + void execute(); + + friend class TaskGroup; }; class TaskGroup { - public: - ~TaskGroup(); - - private: - std::mutex locker = {}; - std::condition_variable condition = {}; - int activeThreads = 0; - bool exited = false; - std::list tasks = {}; - std::vector threads = {}; - - static TaskGroup* GetInstance(); - static void RunLoop(TaskGroup* taskGroup); - - TaskGroup(); - void pushTask(Task* task); - Task* popTask(); - bool removeTask(Task* task); - void exit(); - - friend class Task; +public: + ~TaskGroup(); + +private: + std::mutex locker = {}; + std::condition_variable condition = {}; + int activeThreads = 0; + bool exited = false; + std::list tasks = {}; + std::vector threads = {}; + + static TaskGroup* GetInstance(); + static void RunLoop(TaskGroup* taskGroup); + + TaskGroup(); + void pushTask(Task* task); + Task* popTask(); + bool removeTask(Task* task); + void exit(); + + friend class Task; }; } // namespace pag #else @@ -92,44 +92,44 @@ class TaskGroup { namespace pag { class Executor { - public: - virtual ~Executor() = default; +public: + virtual ~Executor() = default; - private: - virtual void execute() = 0; +private: + virtual void execute() = 0; - friend class Task; + friend class Task; }; class Task { - public: - static std::shared_ptr Make(std::unique_ptr executor) { - return std::shared_ptr(new Task(std::move(executor))); - } - - void run() { - } - - bool isRunning() const { - return running; - } - - Executor* wait() { - running = true; - executor->execute(); - running = false; - return executor.get(); - } - - void cancel() { - } - - private: - bool running = false; - std::unique_ptr executor = nullptr; - - explicit Task(std::unique_ptr executor) : executor(std::move(executor)) { - } +public: + static std::shared_ptr Make(std::unique_ptr executor) { + return std::shared_ptr(new Task(std::move(executor))); + } + + void run() { + } + + bool isRunning() const { + return running; + } + + Executor* wait() { + running = true; + executor->execute(); + running = false; + return executor.get(); + } + + void cancel() { + } + +private: + bool running = false; + std::unique_ptr executor = nullptr; + + explicit Task(std::unique_ptr executor) : executor(std::move(executor)) { + } }; } // namespace pag diff --git a/src/base/utils/TimeUtil.h b/src/base/utils/TimeUtil.h index 646c5f0530..74e489d19d 100644 --- a/src/base/utils/TimeUtil.h +++ b/src/base/utils/TimeUtil.h @@ -23,56 +23,56 @@ namespace pag { inline Frame TimeToFrame(int64_t time, double frameRate) { - return static_cast(floor(time * frameRate / 1000000.0)); + return static_cast(floor(time * frameRate / 1000000.0)); } inline int64_t FrameToTime(Frame frame, double frameRate) { - return static_cast(ceil(frame * 1000000.0 / frameRate)); + return static_cast(ceil(frame * 1000000.0 / frameRate)); } inline Frame ProgressToFrame(double progress, Frame totalFrames) { - if (totalFrames <= 1) { - return 0; - } - auto percent = fmod(progress, 1.0); - if (percent <= 0 && progress != 0) { - percent += 1.0; - } - // 'progress' ranges in [0, 1], but 'frame' ranges in [frame, frame+1), so the last frame needs - // special handling. - auto currentFrame = static_cast(floor(percent * static_cast(totalFrames))); - return currentFrame == totalFrames ? totalFrames - 1 : currentFrame; + if (totalFrames <= 1) { + return 0; + } + auto percent = fmod(progress, 1.0); + if (percent <= 0 && progress != 0) { + percent += 1.0; + } + // 'progress' ranges in [0, 1], but 'frame' ranges in [frame, frame+1), so the last frame needs + // special handling. + auto currentFrame = static_cast(floor(percent * static_cast(totalFrames))); + return currentFrame == totalFrames ? totalFrames - 1 : currentFrame; } inline double FrameToProgress(Frame currentFrame, Frame totalFrames) { - if (totalFrames <= 1 || currentFrame < 0) { - return 0; - } - if (currentFrame >= totalFrames - 1) { - return 1; - } - return currentFrame * 1.0 / totalFrames; + if (totalFrames <= 1 || currentFrame < 0) { + return 0; + } + if (currentFrame >= totalFrames - 1) { + return 1; + } + return currentFrame * 1.0 / totalFrames; } inline int64_t ProgressToTime(double progress, int64_t totalTime) { - if (totalTime <= 1) { - return 0; - } - auto percent = fmod(progress, 1.0); - if (percent <= 0 && progress != 0) { - percent += 1.0; - } - auto currentTime = static_cast(floor(percent * static_cast(totalTime))); - return currentTime == totalTime ? currentTime - 1 : currentTime; + if (totalTime <= 1) { + return 0; + } + auto percent = fmod(progress, 1.0); + if (percent <= 0 && progress != 0) { + percent += 1.0; + } + auto currentTime = static_cast(floor(percent * static_cast(totalTime))); + return currentTime == totalTime ? currentTime - 1 : currentTime; } inline double TimeToProgress(Frame currentFrame, int64_t totalTime) { - if (totalTime <= 1 || currentFrame < 0) { - return 0; - } - if (currentFrame >= totalTime - 1) { - return 1; - } - return currentFrame * 1.0 / totalTime; + if (totalTime <= 1 || currentFrame < 0) { + return 0; + } + if (currentFrame >= totalTime - 1) { + return 1; + } + return currentFrame * 1.0 / totalTime; } } // namespace pag diff --git a/src/base/utils/UTF8Text.cpp b/src/base/utils/UTF8Text.cpp index b17395000f..6dbf6f029c 100644 --- a/src/base/utils/UTF8Text.cpp +++ b/src/base/utils/UTF8Text.cpp @@ -20,37 +20,37 @@ namespace pag { int UTF8Text::Count(const std::string& string) { - if (string.empty()) { - return -1; - } - int count = 0; - const char* start = &(string[0]); - const char* stop = start + string.size(); - while (start < stop) { - NextChar(&start); - ++count; - } - return count; + if (string.empty()) { + return -1; + } + int count = 0; + const char* start = &(string[0]); + const char* stop = start + string.size(); + while (start < stop) { + NextChar(&start); + ++count; + } + return count; } static inline int32_t LeftShift(int32_t value) { - return static_cast((static_cast(value) << 1)); + return static_cast((static_cast(value) << 1)); } int32_t UTF8Text::NextChar(const char** ptr) { - auto p = (const uint8_t*)*ptr; - int c = *p; - int hic = c << 24; - if (hic < 0) { - auto mask = static_cast(~0x3F); - hic = LeftShift(hic); - do { - c = (c << 6) | (*++p & 0x3F); - mask <<= 5; - } while ((hic = LeftShift(hic)) < 0); - c &= ~mask; - } - *ptr = static_cast(static_cast(p + 1)); - return c; + auto p = (const uint8_t*)*ptr; + int c = *p; + int hic = c << 24; + if (hic < 0) { + auto mask = static_cast(~0x3F); + hic = LeftShift(hic); + do { + c = (c << 6) | (*++p & 0x3F); + mask <<= 5; + } while ((hic = LeftShift(hic)) < 0); + c &= ~mask; + } + *ptr = static_cast(static_cast(p + 1)); + return c; } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/UTF8Text.h b/src/base/utils/UTF8Text.h index c4a842a6d6..001f0e1ab0 100644 --- a/src/base/utils/UTF8Text.h +++ b/src/base/utils/UTF8Text.h @@ -23,9 +23,9 @@ namespace pag { class UTF8Text { - public: - static int Count(const std::string& string); +public: + static int Count(const std::string& string); - static int32_t NextChar(const char** ptr); + static int32_t NextChar(const char** ptr); }; } // namespace pag diff --git a/src/base/utils/UniqueID.cpp b/src/base/utils/UniqueID.cpp index d3fac68f56..566c5e3f60 100644 --- a/src/base/utils/UniqueID.cpp +++ b/src/base/utils/UniqueID.cpp @@ -23,6 +23,6 @@ namespace pag { static std::atomic_uint32_t IDCount = {1}; uint32_t UniqueID::Next() { - return IDCount++; + return IDCount++; } } // namespace pag \ No newline at end of file diff --git a/src/base/utils/UniqueID.h b/src/base/utils/UniqueID.h index 3bfe81e3b3..7f44f881a5 100644 --- a/src/base/utils/UniqueID.h +++ b/src/base/utils/UniqueID.h @@ -22,7 +22,7 @@ namespace pag { class UniqueID { - public: - static uint32_t Next(); +public: + static uint32_t Next(); }; } // namespace pag diff --git a/src/codec/AttributeHelper.cpp b/src/codec/AttributeHelper.cpp index e456c09060..352d9b5519 100644 --- a/src/codec/AttributeHelper.cpp +++ b/src/codec/AttributeHelper.cpp @@ -22,45 +22,45 @@ namespace pag { void AddCustomAttribute(BlockConfig* blockConfig, void* target, const std::function reader, const std::function writer) { - blockConfig->targets.push_back(target); - blockConfig->configs.push_back(new CustomAttribute(reader, writer)); + blockConfig->targets.push_back(target); + blockConfig->configs.push_back(new CustomAttribute(reader, writer)); } AttributeFlag ReadAttributeFlag(DecodeStream* stream, const AttributeBase* config) { - AttributeFlag flag = {}; - auto attributeType = config->attributeType; - if (attributeType == AttributeType::FixedValue) { - flag.exist = true; + AttributeFlag flag = {}; + auto attributeType = config->attributeType; + if (attributeType == AttributeType::FixedValue) { + flag.exist = true; + return flag; + } + flag.exist = stream->readBitBoolean(); + if (!flag.exist || attributeType == AttributeType::Value || + attributeType == AttributeType::BitFlag || attributeType == AttributeType::Custom) { + return flag; + } + flag.animatable = stream->readBitBoolean(); + if (!flag.animatable || attributeType != AttributeType::SpatialProperty) { + return flag; + } + flag.hasSpatial = stream->readBitBoolean(); return flag; - } - flag.exist = stream->readBitBoolean(); - if (!flag.exist || attributeType == AttributeType::Value || - attributeType == AttributeType::BitFlag || attributeType == AttributeType::Custom) { - return flag; - } - flag.animatable = stream->readBitBoolean(); - if (!flag.animatable || attributeType != AttributeType::SpatialProperty) { - return flag; - } - flag.hasSpatial = stream->readBitBoolean(); - return flag; } void WriteAttributeFlag(EncodeStream* stream, const AttributeFlag& flag, const AttributeBase* config) { - auto attributeType = config->attributeType; - if (attributeType == AttributeType::FixedValue) { - return; - } - stream->writeBitBoolean(flag.exist); - if (!flag.exist || attributeType == AttributeType::Value || - attributeType == AttributeType::BitFlag || attributeType == AttributeType::Custom) { - return; - } - stream->writeBitBoolean(flag.animatable); - if (!flag.animatable || attributeType != AttributeType::SpatialProperty) { - return; - } - stream->writeBitBoolean(flag.hasSpatial); + auto attributeType = config->attributeType; + if (attributeType == AttributeType::FixedValue) { + return; + } + stream->writeBitBoolean(flag.exist); + if (!flag.exist || attributeType == AttributeType::Value || + attributeType == AttributeType::BitFlag || attributeType == AttributeType::Custom) { + return; + } + stream->writeBitBoolean(flag.animatable); + if (!flag.animatable || attributeType != AttributeType::SpatialProperty) { + return; + } + stream->writeBitBoolean(flag.hasSpatial); } } // namespace pag \ No newline at end of file diff --git a/src/codec/AttributeHelper.h b/src/codec/AttributeHelper.h index bb3c7d7dcc..27acf6dd53 100644 --- a/src/codec/AttributeHelper.h +++ b/src/codec/AttributeHelper.h @@ -23,95 +23,95 @@ namespace pag { enum class AttributeType { - Value, - FixedValue, // always exists, no need to store a flag. - SimpleProperty, - DiscreteProperty, - MultiDimensionProperty, - SpatialProperty, - BitFlag, // save bool value as a flag - Custom // save a flag to indicate whether it should trigger a custom reading/writing action. + Value, + FixedValue, // always exists, no need to store a flag. + SimpleProperty, + DiscreteProperty, + MultiDimensionProperty, + SpatialProperty, + BitFlag, // save bool value as a flag + Custom // save a flag to indicate whether it should trigger a custom reading/writing action. }; struct AttributeFlag { - /** - * Indicates whether or not this value is exist. - */ - bool exist = false; - /** - * Indicates whether or not the size of this property's keyframes is greater than zero. - */ - bool animatable = false; - /** - * Indicates whether or not this property has spatial values. - */ - bool hasSpatial = false; + /** + * Indicates whether or not this value is exist. + */ + bool exist = false; + /** + * Indicates whether or not the size of this property's keyframes is greater than zero. + */ + bool animatable = false; + /** + * Indicates whether or not this property has spatial values. + */ + bool hasSpatial = false; }; class AttributeBase { - public: - AttributeType attributeType; +public: + AttributeType attributeType; - explicit AttributeBase(AttributeType attributeType) : attributeType(attributeType) { - } + explicit AttributeBase(AttributeType attributeType) : attributeType(attributeType) { + } - virtual ~AttributeBase() = default; + virtual ~AttributeBase() = default; - virtual void readAttribute(DecodeStream* stream, const AttributeFlag& flag, - void* target) const = 0; - virtual void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, - void* target) const = 0; + virtual void readAttribute(DecodeStream* stream, const AttributeFlag& flag, + void* target) const = 0; + virtual void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, + void* target) const = 0; }; class CustomAttribute : public AttributeBase { - public: - CustomAttribute(const std::function reader, - const std::function writer) - : AttributeBase(AttributeType::Custom), reader(reader), writer(writer) { - } +public: + CustomAttribute(const std::function reader, + const std::function writer) + : AttributeBase(AttributeType::Custom), reader(reader), writer(writer) { + } - const std::function reader; - const std::function writer; + const std::function reader; + const std::function writer; - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - if (flag.exist) { - reader(stream, target); + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + if (flag.exist) { + reader(stream, target); + } } - } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - auto flag = writer(stream, target); - flagBytes->writeBitBoolean(flag); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + auto flag = writer(stream, target); + flagBytes->writeBitBoolean(flag); + } }; template class AttributeConfig; class BlockConfig { - public: - BlockConfig() : tagCode(TagCode::End) { - } +public: + BlockConfig() : tagCode(TagCode::End) { + } - explicit BlockConfig(TagCode tagCode) : tagCode(tagCode) { - } + explicit BlockConfig(TagCode tagCode) : tagCode(tagCode) { + } - ~BlockConfig() { - for (auto& config : configs) { - delete config; + ~BlockConfig() { + for (auto& config : configs) { + delete config; + } } - } - TagCode tagCode; - std::vector targets = {}; - std::vector configs = {}; + TagCode tagCode; + std::vector targets = {}; + std::vector configs = {}; }; template void AddAttribute(BlockConfig* blockConfig, void* target, AttributeType attributeType, T defaultValue) { - blockConfig->targets.push_back(target); - blockConfig->configs.push_back(new AttributeConfig(attributeType, defaultValue)); + blockConfig->targets.push_back(target); + blockConfig->configs.push_back(new AttributeConfig(attributeType, defaultValue)); } void AddCustomAttribute(BlockConfig* blockConfig, void* target, @@ -122,189 +122,189 @@ AttributeFlag ReadAttributeFlag(DecodeStream* stream, const AttributeBase* confi template T ReadValue(DecodeStream* stream, const AttributeConfig& config, const AttributeFlag& flag) { - if (flag.exist) { - return config.readValue(stream); - } - return config.defaultValue; + if (flag.exist) { + return config.readValue(stream); + } + return config.defaultValue; } template std::vector*> ReadKeyframes(DecodeStream* stream, const AttributeConfig& config, const AttributeFlag& flag) { - std::vector*> keyframes; - auto numFrames = stream->readEncodedUint32(); - for (uint32_t i = 0; i < numFrames; i++) { - Keyframe* keyframe; - if (config.attributeType == AttributeType::DiscreteProperty) { - // There is no need to read any bits here. - keyframe = new Keyframe(); - } else { - auto interpolationType = static_cast(stream->readUBits(2)); - if (interpolationType == KeyframeInterpolationType::Hold) { - keyframe = new Keyframe(); - } else { - keyframe = config.newKeyframe(flag); - keyframe->interpolationType = interpolationType; - } - } - keyframes.push_back(keyframe); - } - return keyframes; + std::vector*> keyframes; + auto numFrames = stream->readEncodedUint32(); + for (uint32_t i = 0; i < numFrames; i++) { + Keyframe* keyframe; + if (config.attributeType == AttributeType::DiscreteProperty) { + // There is no need to read any bits here. + keyframe = new Keyframe(); + } else { + auto interpolationType = static_cast(stream->readUBits(2)); + if (interpolationType == KeyframeInterpolationType::Hold) { + keyframe = new Keyframe(); + } else { + keyframe = config.newKeyframe(flag); + keyframe->interpolationType = interpolationType; + } + } + keyframes.push_back(keyframe); + } + return keyframes; } template void ReadTimeAndValue(DecodeStream* stream, const std::vector*>& keyframes, const AttributeConfig& config) { - auto numFrames = static_cast(keyframes.size()); - keyframes[0]->startTime = ReadTime(stream); - for (uint32_t i = 0; i < numFrames; i++) { - auto time = ReadTime(stream); - keyframes[i]->endTime = time; - if (i < numFrames - 1) { - keyframes[i + 1]->startTime = time; - } - } - auto list = new T[numFrames + 1]; - config.readValueList(stream, list, numFrames + 1); - int index = 0; - keyframes[0]->startValue = list[index++]; - for (uint32_t i = 0; i < numFrames; i++) { - auto value = list[index++]; - keyframes[i]->endValue = value; - if (i < numFrames - 1) { - keyframes[i + 1]->startValue = value; - } - } - delete[] list; + auto numFrames = static_cast(keyframes.size()); + keyframes[0]->startTime = ReadTime(stream); + for (uint32_t i = 0; i < numFrames; i++) { + auto time = ReadTime(stream); + keyframes[i]->endTime = time; + if (i < numFrames - 1) { + keyframes[i + 1]->startTime = time; + } + } + auto list = new T[numFrames + 1]; + config.readValueList(stream, list, numFrames + 1); + int index = 0; + keyframes[0]->startValue = list[index++]; + for (uint32_t i = 0; i < numFrames; i++) { + auto value = list[index++]; + keyframes[i]->endValue = value; + if (i < numFrames - 1) { + keyframes[i + 1]->startValue = value; + } + } + delete[] list; } template void ReadTimeEase(DecodeStream* stream, const std::vector*>& keyframes, const AttributeConfig& config) { - int dimensionality = - config.attributeType == AttributeType::MultiDimensionProperty ? config.dimensionality() : 1; - auto numBits = stream->readNumBits(); - for (auto& keyframe : keyframes) { - if (keyframe->interpolationType != KeyframeInterpolationType::Bezier) { - continue; - } - float x, y; - for (int i = 0; i < dimensionality; i++) { - x = stream->readBits(numBits) * BEZIER_PRECISION; - y = stream->readBits(numBits) * BEZIER_PRECISION; - keyframe->bezierOut.push_back({x, y}); - x = stream->readBits(numBits) * BEZIER_PRECISION; - y = stream->readBits(numBits) * BEZIER_PRECISION; - keyframe->bezierIn.push_back({x, y}); - } - } + int dimensionality = + config.attributeType == AttributeType::MultiDimensionProperty ? config.dimensionality() : 1; + auto numBits = stream->readNumBits(); + for (auto& keyframe : keyframes) { + if (keyframe->interpolationType != KeyframeInterpolationType::Bezier) { + continue; + } + float x, y; + for (int i = 0; i < dimensionality; i++) { + x = stream->readBits(numBits) * BEZIER_PRECISION; + y = stream->readBits(numBits) * BEZIER_PRECISION; + keyframe->bezierOut.push_back({x, y}); + x = stream->readBits(numBits) * BEZIER_PRECISION; + y = stream->readBits(numBits) * BEZIER_PRECISION; + keyframe->bezierIn.push_back({x, y}); + } + } } template void ReadSpatialEase(DecodeStream* stream, const std::vector*>& keyframes) { - auto spatialFlagList = new bool[keyframes.size() * 2]; - auto count = keyframes.size() * 2; - for (size_t i = 0; i < count; i++) { - spatialFlagList[i] = stream->readBitBoolean(); - } - auto numBits = stream->readNumBits(); - int index = 0; - for (auto& keyframe : keyframes) { - auto hasSpatialIn = spatialFlagList[index++]; - auto hasSpatialOut = spatialFlagList[index++]; - if (hasSpatialIn || hasSpatialOut) { - if (hasSpatialIn) { - keyframe->spatialIn.x = stream->readBits(numBits) * SPATIAL_PRECISION; - keyframe->spatialIn.y = stream->readBits(numBits) * SPATIAL_PRECISION; - } - if (hasSpatialOut) { - keyframe->spatialOut.x = stream->readBits(numBits) * SPATIAL_PRECISION; - keyframe->spatialOut.y = stream->readBits(numBits) * SPATIAL_PRECISION; - } - } - } - delete[] spatialFlagList; + auto spatialFlagList = new bool[keyframes.size() * 2]; + auto count = keyframes.size() * 2; + for (size_t i = 0; i < count; i++) { + spatialFlagList[i] = stream->readBitBoolean(); + } + auto numBits = stream->readNumBits(); + int index = 0; + for (auto& keyframe : keyframes) { + auto hasSpatialIn = spatialFlagList[index++]; + auto hasSpatialOut = spatialFlagList[index++]; + if (hasSpatialIn || hasSpatialOut) { + if (hasSpatialIn) { + keyframe->spatialIn.x = stream->readBits(numBits) * SPATIAL_PRECISION; + keyframe->spatialIn.y = stream->readBits(numBits) * SPATIAL_PRECISION; + } + if (hasSpatialOut) { + keyframe->spatialOut.x = stream->readBits(numBits) * SPATIAL_PRECISION; + keyframe->spatialOut.y = stream->readBits(numBits) * SPATIAL_PRECISION; + } + } + } + delete[] spatialFlagList; } template Property* ReadProperty(DecodeStream* stream, const AttributeConfig& config, const AttributeFlag& flag) { - Property* property = nullptr; - if (flag.exist) { - if (flag.animatable) { - auto keyframes = ReadKeyframes(stream, config, flag); - if (keyframes.empty()) { - Throw(stream->context, "Wrong number of keyframes."); - return property; - } - ReadTimeAndValue(stream, keyframes, config); - ReadTimeEase(stream, keyframes, config); - if (flag.hasSpatial) { - ReadSpatialEase(stream, keyframes); - } - property = new AnimatableProperty(keyframes); + Property* property = nullptr; + if (flag.exist) { + if (flag.animatable) { + auto keyframes = ReadKeyframes(stream, config, flag); + if (keyframes.empty()) { + Throw(stream->context, "Wrong number of keyframes."); + return property; + } + ReadTimeAndValue(stream, keyframes, config); + ReadTimeEase(stream, keyframes, config); + if (flag.hasSpatial) { + ReadSpatialEase(stream, keyframes); + } + property = new AnimatableProperty(keyframes); + } else { + property = new Property(); + property->value = ReadValue(stream, config, flag); + } } else { - property = new Property(); - property->value = ReadValue(stream, config, flag); - } - } else { - property = new Property(); - property->value = config.defaultValue; - } - return property; + property = new Property(); + property->value = config.defaultValue; + } + return property; } template void ReadAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target, const AttributeConfig& config) { - if (config.attributeType == AttributeType::BitFlag) { - auto valueTarget = reinterpret_cast(target); - *valueTarget = flag.exist; - } else if (config.attributeType == AttributeType::FixedValue) { - auto valueTarget = reinterpret_cast(target); - *valueTarget = config.readValue(stream); - } else if (config.attributeType == AttributeType::Value) { - auto valueTarget = reinterpret_cast(target); - *valueTarget = ReadValue(stream, config, flag); - } else { - auto propertyTarget = reinterpret_cast**>(target); - *propertyTarget = ReadProperty(stream, config, flag); - } + if (config.attributeType == AttributeType::BitFlag) { + auto valueTarget = reinterpret_cast(target); + *valueTarget = flag.exist; + } else if (config.attributeType == AttributeType::FixedValue) { + auto valueTarget = reinterpret_cast(target); + *valueTarget = config.readValue(stream); + } else if (config.attributeType == AttributeType::Value) { + auto valueTarget = reinterpret_cast(target); + *valueTarget = ReadValue(stream, config, flag); + } else { + auto propertyTarget = reinterpret_cast**>(target); + *propertyTarget = ReadProperty(stream, config, flag); + } } template T* ReadTagBlock(DecodeStream* stream, T* parameter, std::unique_ptr (*ConfigMaker)(T*)) { - auto tagConfig = ConfigMaker(parameter); - - std::vector flags; - for (auto& config : tagConfig->configs) { - auto flag = ReadAttributeFlag(stream, config); - flags.push_back(flag); - } - stream->alignWithBytes(); - int index = 0; - for (auto& config : tagConfig->configs) { - auto flag = flags[index]; - auto target = tagConfig->targets[index]; - config->readAttribute(stream, flag, target); - index++; - } - - return parameter; + auto tagConfig = ConfigMaker(parameter); + + std::vector flags; + for (auto& config : tagConfig->configs) { + auto flag = ReadAttributeFlag(stream, config); + flags.push_back(flag); + } + stream->alignWithBytes(); + int index = 0; + for (auto& config : tagConfig->configs) { + auto flag = flags[index]; + auto target = tagConfig->targets[index]; + config->readAttribute(stream, flag, target); + index++; + } + + return parameter; } template T* ReadTagBlock(DecodeStream* stream, std::unique_ptr (*ConfigMaker)(T*)) { - auto parameter = new T(); - return ReadTagBlock(stream, parameter, ConfigMaker); + auto parameter = new T(); + return ReadTagBlock(stream, parameter, ConfigMaker); } template void ReadBlock(DecodeStream* stream, T* parameter, std::unique_ptr (*ConfigMaker)(T*)) { - stream->alignWithBytes(); - ReadTagBlock(stream, parameter, ConfigMaker); + stream->alignWithBytes(); + ReadTagBlock(stream, parameter, ConfigMaker); } void WriteAttributeFlag(EncodeStream* stream, const AttributeFlag& flag, @@ -312,178 +312,178 @@ void WriteAttributeFlag(EncodeStream* stream, const AttributeFlag& flag, template AttributeFlag WriteValue(EncodeStream* stream, const AttributeConfig& config, const T& value) { - AttributeFlag flag = {}; - if (value == config.defaultValue) { - flag.exist = false; - } else { - flag.exist = true; - config.writeValue(stream, value); - } - return flag; + AttributeFlag flag = {}; + if (value == config.defaultValue) { + flag.exist = false; + } else { + flag.exist = true; + config.writeValue(stream, value); + } + return flag; } template void WriteKeyframes(EncodeStream* stream, const std::vector*>& keyframes, const AttributeConfig& config) { - auto numFrames = keyframes.size(); - stream->writeEncodedUint32(static_cast(numFrames)); - if (config.attributeType == AttributeType::DiscreteProperty) { - return; - } - for (auto& keyframe : keyframes) { - stream->writeUBits(keyframe->interpolationType, 2); - } + auto numFrames = keyframes.size(); + stream->writeEncodedUint32(static_cast(numFrames)); + if (config.attributeType == AttributeType::DiscreteProperty) { + return; + } + for (auto& keyframe : keyframes) { + stream->writeUBits(keyframe->interpolationType, 2); + } } template void WriteTimeAndValue(EncodeStream* stream, const std::vector*>& keyframes, const AttributeConfig& config) { - WriteTime(stream, keyframes[0]->startTime); - for (auto& keyframe : keyframes) { - WriteTime(stream, keyframe->endTime); - } - auto list = new T[keyframes.size() + 1]; - int index = 0; - list[index++] = keyframes[0]->startValue; - for (auto& keyframe : keyframes) { - list[index++] = keyframe->endValue; - } - config.writeValueList(stream, list, static_cast(keyframes.size()) + 1); - delete[] list; + WriteTime(stream, keyframes[0]->startTime); + for (auto& keyframe : keyframes) { + WriteTime(stream, keyframe->endTime); + } + auto list = new T[keyframes.size() + 1]; + int index = 0; + list[index++] = keyframes[0]->startValue; + for (auto& keyframe : keyframes) { + list[index++] = keyframe->endValue; + } + config.writeValueList(stream, list, static_cast(keyframes.size()) + 1); + delete[] list; } template void WriteTimeEase(EncodeStream* stream, const std::vector*>& keyframes, const AttributeConfig& config) { - int dimensionality = - config.attributeType == AttributeType::MultiDimensionProperty ? config.dimensionality() : 1; - std::vector bezierList; - for (auto& keyframe : keyframes) { - if (keyframe->interpolationType != KeyframeInterpolationType::Bezier) { - continue; - } - for (int j = 0; j < dimensionality; j++) { - auto& bezierOut = keyframe->bezierOut[j]; - bezierList.push_back(bezierOut.x); - bezierList.push_back(bezierOut.y); - auto& bezierIn = keyframe->bezierIn[j]; - bezierList.push_back(bezierIn.x); - bezierList.push_back(bezierIn.y); - } - } - auto count = static_cast(bezierList.size()); - stream->writeFloatList(&bezierList[0], count, BEZIER_PRECISION); + int dimensionality = + config.attributeType == AttributeType::MultiDimensionProperty ? config.dimensionality() : 1; + std::vector bezierList; + for (auto& keyframe : keyframes) { + if (keyframe->interpolationType != KeyframeInterpolationType::Bezier) { + continue; + } + for (int j = 0; j < dimensionality; j++) { + auto& bezierOut = keyframe->bezierOut[j]; + bezierList.push_back(bezierOut.x); + bezierList.push_back(bezierOut.y); + auto& bezierIn = keyframe->bezierIn[j]; + bezierList.push_back(bezierIn.x); + bezierList.push_back(bezierIn.y); + } + } + auto count = static_cast(bezierList.size()); + stream->writeFloatList(&bezierList[0], count, BEZIER_PRECISION); } template void WriteSpatialEase(EncodeStream* stream, const std::vector*>& keyframes) { - std::vector spatialList; - for (auto& keyframe : keyframes) { - stream->writeBitBoolean(keyframe->spatialIn != Point::Zero()); - stream->writeBitBoolean(keyframe->spatialOut != Point::Zero()); - if (keyframe->spatialIn != Point::Zero()) { - spatialList.push_back(keyframe->spatialIn.x); - spatialList.push_back(keyframe->spatialIn.y); - } - if (keyframe->spatialOut != Point::Zero()) { - spatialList.push_back(keyframe->spatialOut.x); - spatialList.push_back(keyframe->spatialOut.y); - } - } - auto count = static_cast(spatialList.size()); - stream->writeFloatList(&spatialList[0], count, SPATIAL_PRECISION); + std::vector spatialList; + for (auto& keyframe : keyframes) { + stream->writeBitBoolean(keyframe->spatialIn != Point::Zero()); + stream->writeBitBoolean(keyframe->spatialOut != Point::Zero()); + if (keyframe->spatialIn != Point::Zero()) { + spatialList.push_back(keyframe->spatialIn.x); + spatialList.push_back(keyframe->spatialIn.y); + } + if (keyframe->spatialOut != Point::Zero()) { + spatialList.push_back(keyframe->spatialOut.x); + spatialList.push_back(keyframe->spatialOut.y); + } + } + auto count = static_cast(spatialList.size()); + stream->writeFloatList(&spatialList[0], count, SPATIAL_PRECISION); } template AttributeFlag WriteProperty(EncodeStream* stream, const AttributeConfig& config, Property* property) { - AttributeFlag flag = {}; - if (property == nullptr) { + AttributeFlag flag = {}; + if (property == nullptr) { + return flag; + } + if (!property->animatable()) { + return WriteValue(stream, config, property->getValueAt(0)); + } + flag.exist = true; + flag.animatable = true; + auto& keyframes = static_cast*>(property)->keyframes; + bool hasSpatial = false; + if (config.attributeType == AttributeType::SpatialProperty) { + for (auto keyframe : keyframes) { + if (keyframe->spatialIn != Point::Zero() || keyframe->spatialOut != Point::Zero()) { + hasSpatial = true; + break; + } + } + } + flag.hasSpatial = hasSpatial; + WriteKeyframes(stream, keyframes, config); + WriteTimeAndValue(stream, keyframes, config); + WriteTimeEase(stream, keyframes, config); + if (hasSpatial) { + WriteSpatialEase(stream, keyframes); + } return flag; - } - if (!property->animatable()) { - return WriteValue(stream, config, property->getValueAt(0)); - } - flag.exist = true; - flag.animatable = true; - auto& keyframes = static_cast*>(property)->keyframes; - bool hasSpatial = false; - if (config.attributeType == AttributeType::SpatialProperty) { - for (auto keyframe : keyframes) { - if (keyframe->spatialIn != Point::Zero() || keyframe->spatialOut != Point::Zero()) { - hasSpatial = true; - break; - } - } - } - flag.hasSpatial = hasSpatial; - WriteKeyframes(stream, keyframes, config); - WriteTimeAndValue(stream, keyframes, config); - WriteTimeEase(stream, keyframes, config); - if (hasSpatial) { - WriteSpatialEase(stream, keyframes); - } - return flag; } template void WriteAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target, const AttributeConfig& config) { - AttributeFlag flag = {}; - if (config.attributeType == AttributeType::BitFlag) { - flag.exist = *reinterpret_cast(target); - } else if (config.attributeType == AttributeType::FixedValue) { - flag.exist = true; - auto valueTarget = reinterpret_cast(target); - config.writeValue(stream, *valueTarget); - } else if (config.attributeType == AttributeType::Value) { - auto valueTarget = reinterpret_cast(target); - flag = WriteValue(stream, config, *valueTarget); - } else { - auto propertyTarget = reinterpret_cast**>(target); - flag = WriteProperty(stream, config, *propertyTarget); - } - WriteAttributeFlag(flagBytes, flag, &config); + AttributeFlag flag = {}; + if (config.attributeType == AttributeType::BitFlag) { + flag.exist = *reinterpret_cast(target); + } else if (config.attributeType == AttributeType::FixedValue) { + flag.exist = true; + auto valueTarget = reinterpret_cast(target); + config.writeValue(stream, *valueTarget); + } else if (config.attributeType == AttributeType::Value) { + auto valueTarget = reinterpret_cast(target); + flag = WriteValue(stream, config, *valueTarget); + } else { + auto propertyTarget = reinterpret_cast**>(target); + flag = WriteProperty(stream, config, *propertyTarget); + } + WriteAttributeFlag(flagBytes, flag, &config); } template void WriteTagBlock(EncodeStream* stream, T* parameter, std::unique_ptr (*ConfigMaker)(T*)) { - EncodeStream flagBytes(stream->context); - EncodeStream bytes(stream->context); - auto tagConfig = ConfigMaker(parameter); - int index = 0; - for (auto& config : tagConfig->configs) { - auto target = tagConfig->targets[index]; - config->writeAttribute(&flagBytes, &bytes, target); - index++; - } - // Actually the alignWithBytes() here has no effect, - // it is just for reminding us that we need to call - // alignWithBytes() when start reading this block. - flagBytes.alignWithBytes(); - flagBytes.writeBytes(&bytes); - WriteTagHeader(stream, &flagBytes, tagConfig->tagCode); + EncodeStream flagBytes(stream->context); + EncodeStream bytes(stream->context); + auto tagConfig = ConfigMaker(parameter); + int index = 0; + for (auto& config : tagConfig->configs) { + auto target = tagConfig->targets[index]; + config->writeAttribute(&flagBytes, &bytes, target); + index++; + } + // Actually the alignWithBytes() here has no effect, + // it is just for reminding us that we need to call + // alignWithBytes() when start reading this block. + flagBytes.alignWithBytes(); + flagBytes.writeBytes(&bytes); + WriteTagHeader(stream, &flagBytes, tagConfig->tagCode); } template void WriteBlock(EncodeStream* stream, T* parameter, std::unique_ptr (*ConfigMaker)(T*)) { - // Must call alignWithBytes() here in case - // we have already written some bit values in stream. - stream->alignWithBytes(); - EncodeStream contentBytes(stream->context); - auto tagConfig = ConfigMaker(parameter); - int index = 0; - for (auto& config : tagConfig->configs) { - auto target = tagConfig->targets[index]; - config->writeAttribute(stream, &contentBytes, target); - index++; - } - // Actually the alignWithBytes() here has no effect, - // it is just for reminding us that we need to call - // alignWithBytes() when start reading this block. - stream->alignWithBytes(); - stream->writeBytes(&contentBytes); + // Must call alignWithBytes() here in case + // we have already written some bit values in stream. + stream->alignWithBytes(); + EncodeStream contentBytes(stream->context); + auto tagConfig = ConfigMaker(parameter); + int index = 0; + for (auto& config : tagConfig->configs) { + auto target = tagConfig->targets[index]; + config->writeAttribute(stream, &contentBytes, target); + index++; + } + // Actually the alignWithBytes() here has no effect, + // it is just for reminding us that we need to call + // alignWithBytes() when start reading this block. + stream->alignWithBytes(); + stream->writeBytes(&contentBytes); } } // namespace pag diff --git a/src/codec/Attributes.h b/src/codec/Attributes.h index cdbdf33931..481248ea17 100644 --- a/src/codec/Attributes.h +++ b/src/codec/Attributes.h @@ -23,756 +23,756 @@ namespace pag { template class AttributeConfigBase { - public: - virtual ~AttributeConfigBase() { - } +public: + virtual ~AttributeConfigBase() { + } - virtual int dimensionality() const { - return 1; - } + virtual int dimensionality() const { + return 1; + } - virtual Keyframe* newKeyframe(const AttributeFlag&) const { - return new Keyframe(); - } + virtual Keyframe* newKeyframe(const AttributeFlag&) const { + return new Keyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - float defaultValue; +public: + float defaultValue; - AttributeConfig(AttributeType attributeType, float defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, float defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - float readValue(DecodeStream* stream) const { - return stream->readFloat(); - } + float readValue(DecodeStream* stream) const { + return stream->readFloat(); + } - void writeValue(EncodeStream* stream, const float& value) const { - stream->writeFloat(value); - } + void writeValue(EncodeStream* stream, const float& value) const { + stream->writeFloat(value); + } - void readValueList(DecodeStream* stream, float* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, float* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const float* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const float* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - bool defaultValue; +public: + bool defaultValue; - AttributeConfig(AttributeType attributeType, bool defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, bool defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - bool readValue(DecodeStream* stream) const { - return stream->readBoolean(); - } + bool readValue(DecodeStream* stream) const { + return stream->readBoolean(); + } - void writeValue(EncodeStream* stream, const bool& value) const { - stream->writeBoolean(value); - } + void writeValue(EncodeStream* stream, const bool& value) const { + stream->writeBoolean(value); + } - void readValueList(DecodeStream* stream, bool* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = stream->readBitBoolean(); + void readValueList(DecodeStream* stream, bool* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = stream->readBitBoolean(); + } } - } - void writeValueList(EncodeStream* stream, const bool* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - stream->writeBitBoolean(list[i]); + void writeValueList(EncodeStream* stream, const bool* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + stream->writeBitBoolean(list[i]); + } } - } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - uint8_t defaultValue; - - AttributeConfig(AttributeType attributeType, uint8_t defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } - - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } - - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } - - uint8_t readValue(DecodeStream* stream) const { - return stream->readUint8(); - } - - void writeValue(EncodeStream* stream, const uint8_t& value) const { - stream->writeUint8(value); - } - - void readValueList(DecodeStream* stream, uint8_t* list, uint32_t count) const { - auto valueList = new uint32_t[count]; - stream->readUint32List(valueList, count); - for (uint32_t i = 0; i < count; i++) { - list[i] = static_cast(valueList[i]); - } - delete[] valueList; - } - - void writeValueList(EncodeStream* stream, const uint8_t* list, uint32_t count) const { - auto valueList = new uint32_t[count]; - for (uint32_t i = 0; i < count; i++) { - valueList[i] = list[i]; - } - stream->writeUint32List(valueList, count); - delete[] valueList; - } - - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } +public: + uint8_t defaultValue; + + AttributeConfig(AttributeType attributeType, uint8_t defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } + + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } + + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } + + uint8_t readValue(DecodeStream* stream) const { + return stream->readUint8(); + } + + void writeValue(EncodeStream* stream, const uint8_t& value) const { + stream->writeUint8(value); + } + + void readValueList(DecodeStream* stream, uint8_t* list, uint32_t count) const { + auto valueList = new uint32_t[count]; + stream->readUint32List(valueList, count); + for (uint32_t i = 0; i < count; i++) { + list[i] = static_cast(valueList[i]); + } + delete[] valueList; + } + + void writeValueList(EncodeStream* stream, const uint8_t* list, uint32_t count) const { + auto valueList = new uint32_t[count]; + for (uint32_t i = 0; i < count; i++) { + valueList[i] = list[i]; + } + stream->writeUint32List(valueList, count); + delete[] valueList; + } + + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - uint16_t defaultValue; - - AttributeConfig(AttributeType attributeType, uint16_t defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } - - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } - - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } - - uint16_t readValue(DecodeStream* stream) const { - auto value = stream->readEncodedUint32(); - return static_cast(value); - } - - void writeValue(EncodeStream* stream, const uint16_t& value) const { - stream->writeEncodedUint32(static_cast(value)); - } - - void readValueList(DecodeStream* stream, uint16_t* list, uint32_t count) const { - auto valueList = new uint32_t[count]; - stream->readUint32List(valueList, count); - for (uint32_t i = 0; i < count; i++) { - list[i] = static_cast(valueList[i]); - } - delete[] valueList; - } - - void writeValueList(EncodeStream* stream, const uint16_t* list, uint32_t count) const { - auto valueList = new uint32_t[count]; - for (uint32_t i = 0; i < count; i++) { - valueList[i] = list[i]; - } - stream->writeUint32List(valueList, count); - delete[] valueList; - } - - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } +public: + uint16_t defaultValue; + + AttributeConfig(AttributeType attributeType, uint16_t defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } + + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } + + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } + + uint16_t readValue(DecodeStream* stream) const { + auto value = stream->readEncodedUint32(); + return static_cast(value); + } + + void writeValue(EncodeStream* stream, const uint16_t& value) const { + stream->writeEncodedUint32(static_cast(value)); + } + + void readValueList(DecodeStream* stream, uint16_t* list, uint32_t count) const { + auto valueList = new uint32_t[count]; + stream->readUint32List(valueList, count); + for (uint32_t i = 0; i < count; i++) { + list[i] = static_cast(valueList[i]); + } + delete[] valueList; + } + + void writeValueList(EncodeStream* stream, const uint16_t* list, uint32_t count) const { + auto valueList = new uint32_t[count]; + for (uint32_t i = 0; i < count; i++) { + valueList[i] = list[i]; + } + stream->writeUint32List(valueList, count); + delete[] valueList; + } + + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - uint32_t defaultValue; +public: + uint32_t defaultValue; - AttributeConfig(AttributeType attributeType, uint32_t defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, uint32_t defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - uint32_t readValue(DecodeStream* stream) const { - return stream->readEncodedUint32(); - } + uint32_t readValue(DecodeStream* stream) const { + return stream->readEncodedUint32(); + } - void writeValue(EncodeStream* stream, const uint32_t& value) const { - stream->writeEncodedUint32(value); - } + void writeValue(EncodeStream* stream, const uint32_t& value) const { + stream->writeEncodedUint32(value); + } - void readValueList(DecodeStream* stream, uint32_t* list, uint32_t count) const { - stream->readUint32List(list, count); - } + void readValueList(DecodeStream* stream, uint32_t* list, uint32_t count) const { + stream->readUint32List(list, count); + } - void writeValueList(EncodeStream* stream, const uint32_t* list, uint32_t count) const { - stream->writeUint32List(list, count); - } + void writeValueList(EncodeStream* stream, const uint32_t* list, uint32_t count) const { + stream->writeUint32List(list, count); + } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - int32_t defaultValue; +public: + int32_t defaultValue; - AttributeConfig(AttributeType attributeType, int32_t defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, int32_t defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - int32_t readValue(DecodeStream* stream) const { - return stream->readEncodedInt32(); - } + int32_t readValue(DecodeStream* stream) const { + return stream->readEncodedInt32(); + } - void writeValue(EncodeStream* stream, const int32_t& value) const { - stream->writeEncodedInt32(value); - } + void writeValue(EncodeStream* stream, const int32_t& value) const { + stream->writeEncodedInt32(value); + } - void readValueList(DecodeStream* stream, int32_t* list, uint32_t count) const { - stream->readInt32List(list, count); - } + void readValueList(DecodeStream* stream, int32_t* list, uint32_t count) const { + stream->readInt32List(list, count); + } - void writeValueList(EncodeStream* stream, const int32_t* list, uint32_t count) const { - stream->writeInt32List(list, count); - } + void writeValueList(EncodeStream* stream, const int32_t* list, uint32_t count) const { + stream->writeInt32List(list, count); + } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - Frame defaultValue; +public: + Frame defaultValue; - AttributeConfig(AttributeType attributeType, Frame defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, Frame defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - Frame readValue(DecodeStream* stream) const { - return ReadTime(stream); - } + Frame readValue(DecodeStream* stream) const { + return ReadTime(stream); + } - void writeValue(EncodeStream* stream, const Frame& value) const { - WriteTime(stream, value); - } + void writeValue(EncodeStream* stream, const Frame& value) const { + WriteTime(stream, value); + } - void readValueList(DecodeStream* stream, Frame* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, Frame* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const Frame* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const Frame* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - Point defaultValue; - - AttributeConfig(AttributeType attributeType, Point defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } - - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } - - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } - - int dimensionality() const override { - return 2; - } - - Point readValue(DecodeStream* stream) const { - return ReadPoint(stream); - } - - void writeValue(EncodeStream* stream, const Point& value) const { - WritePoint(stream, value); - } - - void readValueList(DecodeStream* stream, Point* list, uint32_t count) const { - if (attributeType == AttributeType::SpatialProperty) { - stream->readFloatList(&(list[0].x), count * 2, SPATIAL_PRECISION); - } else { - for (uint32_t i = 0; i < count; i++) { - list[i] = ReadPoint(stream); - } - } - } - - void writeValueList(EncodeStream* stream, const Point* list, uint32_t count) const { - if (attributeType == AttributeType::SpatialProperty) { - stream->writeFloatList(&(list[0].x), count * 2, SPATIAL_PRECISION); - } else { - for (uint32_t i = 0; i < count; i++) { - WritePoint(stream, list[i]); - } - } - } - - Keyframe* newKeyframe(const AttributeFlag& flag) const override { - switch (attributeType) { - case AttributeType::MultiDimensionProperty: - return new MultiDimensionPointKeyframe(); - case AttributeType::SpatialProperty: - if (flag.hasSpatial) { - return new SpatialPointKeyframe(); - } - default: - return new SingleEaseKeyframe(); - } - } +public: + Point defaultValue; + + AttributeConfig(AttributeType attributeType, Point defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } + + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } + + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } + + int dimensionality() const override { + return 2; + } + + Point readValue(DecodeStream* stream) const { + return ReadPoint(stream); + } + + void writeValue(EncodeStream* stream, const Point& value) const { + WritePoint(stream, value); + } + + void readValueList(DecodeStream* stream, Point* list, uint32_t count) const { + if (attributeType == AttributeType::SpatialProperty) { + stream->readFloatList(&(list[0].x), count * 2, SPATIAL_PRECISION); + } else { + for (uint32_t i = 0; i < count; i++) { + list[i] = ReadPoint(stream); + } + } + } + + void writeValueList(EncodeStream* stream, const Point* list, uint32_t count) const { + if (attributeType == AttributeType::SpatialProperty) { + stream->writeFloatList(&(list[0].x), count * 2, SPATIAL_PRECISION); + } else { + for (uint32_t i = 0; i < count; i++) { + WritePoint(stream, list[i]); + } + } + } + + Keyframe* newKeyframe(const AttributeFlag& flag) const override { + switch (attributeType) { + case AttributeType::MultiDimensionProperty: + return new MultiDimensionPointKeyframe(); + case AttributeType::SpatialProperty: + if (flag.hasSpatial) { + return new SpatialPointKeyframe(); + } + default: + return new SingleEaseKeyframe(); + } + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - Color defaultValue; +public: + Color defaultValue; - AttributeConfig(AttributeType attributeType, Color defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, Color defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - int dimensionality() const override { - return 3; - } + int dimensionality() const override { + return 3; + } - Color readValue(DecodeStream* stream) const { - return ReadColor(stream); - } + Color readValue(DecodeStream* stream) const { + return ReadColor(stream); + } - void writeValue(EncodeStream* stream, const Color& value) const { - WriteColor(stream, value); - } + void writeValue(EncodeStream* stream, const Color& value) const { + WriteColor(stream, value); + } - void readValueList(DecodeStream* stream, Color* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, Color* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const Color* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const Color* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - Ratio defaultValue; +public: + Ratio defaultValue; - AttributeConfig(AttributeType attributeType, Ratio defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, Ratio defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - Ratio readValue(DecodeStream* stream) const { - return ReadRatio(stream); - } + Ratio readValue(DecodeStream* stream) const { + return ReadRatio(stream); + } - void writeValue(EncodeStream* stream, const Ratio& value) const { - WriteRatio(stream, value); - } + void writeValue(EncodeStream* stream, const Ratio& value) const { + WriteRatio(stream, value); + } - void readValueList(DecodeStream* stream, Ratio* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, Ratio* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const Ratio* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const Ratio* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - std::string defaultValue; +public: + std::string defaultValue; - AttributeConfig(AttributeType attributeType, std::string defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, std::string defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - std::string readValue(DecodeStream* stream) const { - return stream->readUTF8String(); - } + std::string readValue(DecodeStream* stream) const { + return stream->readUTF8String(); + } - void writeValue(EncodeStream* stream, const std::string& value) const { - stream->writeUTF8String(value); - } + void writeValue(EncodeStream* stream, const std::string& value) const { + stream->writeUTF8String(value); + } - void readValueList(DecodeStream* stream, std::string* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, std::string* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const std::string* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const std::string* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new Keyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new Keyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - PathHandle defaultValue; +public: + PathHandle defaultValue; - AttributeConfig(AttributeType attributeType, PathHandle defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, PathHandle defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - PathHandle readValue(DecodeStream* stream) const { - return ReadPath(stream); - } + PathHandle readValue(DecodeStream* stream) const { + return ReadPath(stream); + } - void writeValue(EncodeStream* stream, const PathHandle& value) const { - WritePath(stream, value); - } + void writeValue(EncodeStream* stream, const PathHandle& value) const { + WritePath(stream, value); + } - void readValueList(DecodeStream* stream, PathHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, PathHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const PathHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const PathHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, - public AttributeConfigBase { - public: - TextDocumentHandle defaultValue; - - AttributeConfig(AttributeType attributeType, TextDocumentHandle defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } - - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } - - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } - - TextDocumentHandle readValue(DecodeStream* stream) const { - // 外面根据 tag V1/V2/V3 设置了 defaultValue, - // 这里根据 defaultValue 决定使用哪个 TAG 来读 - if (defaultValue->direction != TextDirection::Default) { - return ReadTextDocumentV3(stream); - } else if (defaultValue->backgroundAlpha != 0) { - return ReadTextDocumentV2(stream); - } else { - return ReadTextDocument(stream); - } - } - - void writeValue(EncodeStream* stream, const TextDocumentHandle& value) const { - // 外面根据 tag V1/V2/V3 设置了 defaultValue, - // 这里根据 defaultValue 决定使用哪个 TAG 来写 - if (defaultValue->direction != TextDirection::Default) { - WriteTextDocumentV3(stream, value); - } else if (defaultValue->backgroundAlpha != 0) { - WriteTextDocumentV2(stream, value); - } else { - WriteTextDocument(stream, value); - } - } - - void readValueList(DecodeStream* stream, TextDocumentHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); - } - } - - void writeValueList(EncodeStream* stream, const TextDocumentHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); - } - } + public AttributeConfigBase { +public: + TextDocumentHandle defaultValue; + + AttributeConfig(AttributeType attributeType, TextDocumentHandle defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } + + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } + + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } + + TextDocumentHandle readValue(DecodeStream* stream) const { + // 外面根据 tag V1/V2/V3 设置了 defaultValue, + // 这里根据 defaultValue 决定使用哪个 TAG 来读 + if (defaultValue->direction != TextDirection::Default) { + return ReadTextDocumentV3(stream); + } else if (defaultValue->backgroundAlpha != 0) { + return ReadTextDocumentV2(stream); + } else { + return ReadTextDocument(stream); + } + } + + void writeValue(EncodeStream* stream, const TextDocumentHandle& value) const { + // 外面根据 tag V1/V2/V3 设置了 defaultValue, + // 这里根据 defaultValue 决定使用哪个 TAG 来写 + if (defaultValue->direction != TextDirection::Default) { + WriteTextDocumentV3(stream, value); + } else if (defaultValue->backgroundAlpha != 0) { + WriteTextDocumentV2(stream, value); + } else { + WriteTextDocument(stream, value); + } + } + + void readValueList(DecodeStream* stream, TextDocumentHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } + } + + void writeValueList(EncodeStream* stream, const TextDocumentHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } + } }; template <> class AttributeConfig : public AttributeBase, - public AttributeConfigBase { - public: - GradientColorHandle defaultValue; + public AttributeConfigBase { +public: + GradientColorHandle defaultValue; - AttributeConfig(AttributeType attributeType, GradientColorHandle defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, GradientColorHandle defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - GradientColorHandle readValue(DecodeStream* stream) const { - return ReadGradientColor(stream); - } + GradientColorHandle readValue(DecodeStream* stream) const { + return ReadGradientColor(stream); + } - void writeValue(EncodeStream* stream, const GradientColorHandle& value) const { - WriteGradientColor(stream, value); - } + void writeValue(EncodeStream* stream, const GradientColorHandle& value) const { + WriteGradientColor(stream, value); + } - void readValueList(DecodeStream* stream, GradientColorHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, GradientColorHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, const GradientColorHandle* list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, const GradientColorHandle* list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } - Keyframe* newKeyframe(const AttributeFlag&) const override { - return new SingleEaseKeyframe(); - } + Keyframe* newKeyframe(const AttributeFlag&) const override { + return new SingleEaseKeyframe(); + } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - Layer* defaultValue; +public: + Layer* defaultValue; - AttributeConfig(AttributeType attributeType, Layer* defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, Layer* defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - Layer* readValue(DecodeStream* stream) const { - return ReadLayerID(stream); - } + Layer* readValue(DecodeStream* stream) const { + return ReadLayerID(stream); + } - void writeValue(EncodeStream* stream, const Layer* value) const { - WriteLayerID(stream, const_cast(value)); - } + void writeValue(EncodeStream* stream, const Layer* value) const { + WriteLayerID(stream, const_cast(value)); + } - void readValueList(DecodeStream* stream, Layer** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, Layer** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, Layer** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, Layer** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } }; template <> class AttributeConfig : public AttributeBase, public AttributeConfigBase { - public: - MaskData* defaultValue; +public: + MaskData* defaultValue; - AttributeConfig(AttributeType attributeType, MaskData* defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, MaskData* defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - MaskData* readValue(DecodeStream* stream) const { - return ReadMaskID(stream); - } + MaskData* readValue(DecodeStream* stream) const { + return ReadMaskID(stream); + } - void writeValue(EncodeStream* stream, const MaskData* value) const { - WriteMaskID(stream, const_cast(value)); - } + void writeValue(EncodeStream* stream, const MaskData* value) const { + WriteMaskID(stream, const_cast(value)); + } - void readValueList(DecodeStream* stream, MaskData** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, MaskData** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, MaskData** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, MaskData** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } }; template <> class AttributeConfig : public AttributeBase, - public AttributeConfigBase { - public: - Composition* defaultValue; + public AttributeConfigBase { +public: + Composition* defaultValue; - AttributeConfig(AttributeType attributeType, Composition* defaultValue) - : AttributeBase(attributeType), defaultValue(defaultValue) { - } + AttributeConfig(AttributeType attributeType, Composition* defaultValue) + : AttributeBase(attributeType), defaultValue(defaultValue) { + } - void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { - ReadAttribute(stream, flag, target, *this); - } + void readAttribute(DecodeStream* stream, const AttributeFlag& flag, void* target) const override { + ReadAttribute(stream, flag, target, *this); + } - void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { - WriteAttribute(flagBytes, stream, target, *this); - } + void writeAttribute(EncodeStream* flagBytes, EncodeStream* stream, void* target) const override { + WriteAttribute(flagBytes, stream, target, *this); + } - Composition* readValue(DecodeStream* stream) const { - return ReadCompositionID(stream); - } + Composition* readValue(DecodeStream* stream) const { + return ReadCompositionID(stream); + } - void writeValue(EncodeStream* stream, const Composition* value) const { - WriteCompositionID(stream, const_cast(value)); - } + void writeValue(EncodeStream* stream, const Composition* value) const { + WriteCompositionID(stream, const_cast(value)); + } - void readValueList(DecodeStream* stream, Composition** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - list[i] = readValue(stream); + void readValueList(DecodeStream* stream, Composition** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + list[i] = readValue(stream); + } } - } - void writeValueList(EncodeStream* stream, Composition** list, uint32_t count) const { - for (uint32_t i = 0; i < count; i++) { - writeValue(stream, list[i]); + void writeValueList(EncodeStream* stream, Composition** list, uint32_t count) const { + for (uint32_t i = 0; i < count; i++) { + writeValue(stream, list[i]); + } } - } }; } // namespace pag diff --git a/src/codec/Codec.cpp b/src/codec/Codec.cpp index 39a5f5dd79..ad9104c2a2 100644 --- a/src/codec/Codec.cpp +++ b/src/codec/Codec.cpp @@ -31,252 +31,252 @@ namespace pag { static const uint8_t CompatibleVersion = 2; static bool HasTrackMatte(Enum type) { - switch (type) { + switch (type) { case TrackMatteType::Alpha: case TrackMatteType::AlphaInverted: - return true; + return true; default: - return false; - } + return false; + } } uint16_t Codec::MaxSupportedTagLevel() { - return static_cast(TagCode::Count) - 1; + return static_cast(TagCode::Count) - 1; } void Codec::InstallReferences(Layer* layer) { - std::unordered_map maskMap; - for (auto mask : layer->masks) { - maskMap.insert(std::make_pair(mask->id, mask)); - } - for (auto effect : layer->effects) { - if (!effect->maskReferences.empty()) { - for (auto i = static_cast(effect->maskReferences.size() - 1); i >= 0; i--) { - auto id = effect->maskReferences[i]->id; - delete effect->maskReferences[i]; - auto result = maskMap.find(id); - if (result != maskMap.end()) { - effect->maskReferences[i] = result->second; - } else { - effect->maskReferences.erase(effect->maskReferences.begin() + i); + std::unordered_map maskMap; + for (auto mask : layer->masks) { + maskMap.insert(std::make_pair(mask->id, mask)); + } + for (auto effect : layer->effects) { + if (!effect->maskReferences.empty()) { + for (auto i = static_cast(effect->maskReferences.size() - 1); i >= 0; i--) { + auto id = effect->maskReferences[i]->id; + delete effect->maskReferences[i]; + auto result = maskMap.find(id); + if (result != maskMap.end()) { + effect->maskReferences[i] = result->second; + } else { + effect->maskReferences.erase(effect->maskReferences.begin() + i); + } + } } - } } - } - if (layer->type() == LayerType::Text) { - auto pathOption = static_cast(layer)->pathOption; - if (pathOption && pathOption->path) { - auto id = pathOption->path->id; - delete pathOption->path; - pathOption->path = nullptr; - auto result = maskMap.find(id); - if (result != maskMap.end()) { - pathOption->path = result->second; - } + if (layer->type() == LayerType::Text) { + auto pathOption = static_cast(layer)->pathOption; + if (pathOption && pathOption->path) { + auto id = pathOption->path->id; + delete pathOption->path; + pathOption->path = nullptr; + auto result = maskMap.find(id); + if (result != maskMap.end()) { + pathOption->path = result->second; + } + } } - } } void Codec::InstallReferences(const std::vector& layers) { - std::unordered_map layerMap; - std::for_each(layers.begin(), layers.end(), [&layerMap](Layer* layer) { - InstallReferences(layer); - layerMap.insert(std::make_pair(layer->id, layer)); - }); - int index = 0; - for (auto layer : layers) { - if (layer->parent) { - auto id = layer->parent->id; - delete layer->parent; - layer->parent = nullptr; - auto result = layerMap.find(id); - if (result != layerMap.end()) { - layer->parent = result->second; - } - } - if (index > 0 && HasTrackMatte(layer->trackMatteType)) { - layer->trackMatteLayer = layers[index - 1]; - } - for (auto effect : layer->effects) { - auto displacementMap = static_cast(effect); - if (effect->type() == EffectType::DisplacementMap && displacementMap->displacementMapLayer) { - auto id = displacementMap->displacementMapLayer->id; - delete displacementMap->displacementMapLayer; - displacementMap->displacementMapLayer = nullptr; - auto result = layerMap.find(id); - if (result != layerMap.end()) { - displacementMap->displacementMapLayer = result->second; + std::unordered_map layerMap; + std::for_each(layers.begin(), layers.end(), [&layerMap](Layer* layer) { + InstallReferences(layer); + layerMap.insert(std::make_pair(layer->id, layer)); + }); + int index = 0; + for (auto layer : layers) { + if (layer->parent) { + auto id = layer->parent->id; + delete layer->parent; + layer->parent = nullptr; + auto result = layerMap.find(id); + if (result != layerMap.end()) { + layer->parent = result->second; + } + } + if (index > 0 && HasTrackMatte(layer->trackMatteType)) { + layer->trackMatteLayer = layers[index - 1]; + } + for (auto effect : layer->effects) { + auto displacementMap = static_cast(effect); + if (effect->type() == EffectType::DisplacementMap && displacementMap->displacementMapLayer) { + auto id = displacementMap->displacementMapLayer->id; + delete displacementMap->displacementMapLayer; + displacementMap->displacementMapLayer = nullptr; + auto result = layerMap.find(id); + if (result != layerMap.end()) { + displacementMap->displacementMapLayer = result->second; + } + } } - } + index++; } - index++; - } } void Codec::InstallReferences(const std::vector& compositions) { - std::unordered_map compositionMap; - for (auto composition : compositions) { - compositionMap.insert(std::make_pair(composition->id, composition)); - } - for (auto item : compositions) { - if (item->type() == CompositionType::Vector) { - for (auto layer : static_cast(item)->layers) { - layer->containingComposition = static_cast(item); - auto preComposeLayer = static_cast(layer); - if (layer->type() == LayerType::PreCompose && preComposeLayer->composition) { - auto id = preComposeLayer->composition->id; - delete preComposeLayer->composition; - preComposeLayer->composition = nullptr; - auto result = compositionMap.find(id); - if (result != compositionMap.end()) { - preComposeLayer->composition = result->second; - } + std::unordered_map compositionMap; + for (auto composition : compositions) { + compositionMap.insert(std::make_pair(composition->id, composition)); + } + for (auto item : compositions) { + if (item->type() == CompositionType::Vector) { + for (auto layer : static_cast(item)->layers) { + layer->containingComposition = static_cast(item); + auto preComposeLayer = static_cast(layer); + if (layer->type() == LayerType::PreCompose && preComposeLayer->composition) { + auto id = preComposeLayer->composition->id; + delete preComposeLayer->composition; + preComposeLayer->composition = nullptr; + auto result = compositionMap.find(id); + if (result != compositionMap.end()) { + preComposeLayer->composition = result->second; + } + } + } } - } } - } } std::shared_ptr Codec::VerifyAndMake(const std::vector& compositions, - const std::vector& images) { - bool success = !compositions.empty(); - for (auto composition : compositions) { - if (composition == nullptr || !composition->verify()) { - success = false; - break; - } - } - for (auto& imageBytes : images) { - if (imageBytes == nullptr || !imageBytes->verify()) { - success = false; - break; - } - } - if (!success) { - for (auto& composition : compositions) { - delete composition; + const std::vector& images) { + bool success = !compositions.empty(); + for (auto composition : compositions) { + if (composition == nullptr || !composition->verify()) { + success = false; + break; + } } for (auto& imageBytes : images) { - delete imageBytes; + if (imageBytes == nullptr || !imageBytes->verify()) { + success = false; + break; + } } - return nullptr; - } - auto file = new File(compositions, images); - return std::shared_ptr(file); + if (!success) { + for (auto& composition : compositions) { + delete composition; + } + for (auto& imageBytes : images) { + delete imageBytes; + } + return nullptr; + } + auto file = new File(compositions, images); + return std::shared_ptr(file); } DecodeStream ReadBodyBytes(DecodeStream* stream) { - DecodeStream emptyStream(stream->context); - if (stream->length() < 11) { - Throw(stream->context, "Length of PAG file is too short."); - return emptyStream; - } - auto P = stream->readInt8(); - auto A = stream->readInt8(); - auto G = stream->readInt8(); - if (P != 'P' || A != 'A' || G != 'G') { - Throw(stream->context, "Invalid PAG file header."); - return emptyStream; - } - auto version = stream->readUint8(); - if (version > CompatibleVersion) { - Throw(stream->context, "Invalid PAG file header."); - return emptyStream; - } - auto bodyLength = stream->readUint32(); - auto compression = stream->readInt8(); - if (compression != CompressionAlgorithm::UNCOMPRESSED) { - Throw(stream->context, "Invalid PAG file header."); - return emptyStream; - } - bodyLength = std::min(bodyLength, stream->bytesAvailable()); - return stream->readBytes(bodyLength); + DecodeStream emptyStream(stream->context); + if (stream->length() < 11) { + Throw(stream->context, "Length of PAG file is too short."); + return emptyStream; + } + auto P = stream->readInt8(); + auto A = stream->readInt8(); + auto G = stream->readInt8(); + if (P != 'P' || A != 'A' || G != 'G') { + Throw(stream->context, "Invalid PAG file header."); + return emptyStream; + } + auto version = stream->readUint8(); + if (version > CompatibleVersion) { + Throw(stream->context, "Invalid PAG file header."); + return emptyStream; + } + auto bodyLength = stream->readUint32(); + auto compression = stream->readInt8(); + if (compression != CompressionAlgorithm::UNCOMPRESSED) { + Throw(stream->context, "Invalid PAG file header."); + return emptyStream; + } + bodyLength = std::min(bodyLength, stream->bytesAvailable()); + return stream->readBytes(bodyLength); } std::shared_ptr Codec::Decode(const void* bytes, uint32_t byteLength, const std::string& filePath) { - CodecContext context = {}; - DecodeStream stream(&context, reinterpret_cast(bytes), byteLength); - auto bodyBytes = ReadBodyBytes(&stream); - if (context.hasException()) { - return nullptr; - } - ReadTags(&bodyBytes, &context, ReadTagsOfFile); - InstallReferences(context.compositions); - if (context.hasException()) { - return nullptr; - } + CodecContext context = {}; + DecodeStream stream(&context, reinterpret_cast(bytes), byteLength); + auto bodyBytes = ReadBodyBytes(&stream); + if (context.hasException()) { + return nullptr; + } + ReadTags(&bodyBytes, &context, ReadTagsOfFile); + InstallReferences(context.compositions); + if (context.hasException()) { + return nullptr; + } - // Verify 提前到使用之前,避免未经Verify导致使用时crash - auto file = VerifyAndMake(context.releaseCompositions(), context.releaseImages()); - if (file == nullptr) { - return nullptr; - } + // Verify 提前到使用之前,避免未经Verify导致使用时crash + auto file = VerifyAndMake(context.releaseCompositions(), context.releaseImages()); + if (file == nullptr) { + return nullptr; + } - for (auto& composition : file->compositions) { - if (!composition->staticTimeRangeUpdated) { - composition->updateStaticTimeRanges(); - composition->staticTimeRangeUpdated = true; + for (auto& composition : file->compositions) { + if (!composition->staticTimeRangeUpdated) { + composition->updateStaticTimeRanges(); + composition->staticTimeRangeUpdated = true; + } } - } - if (context.scaledTimeRange != nullptr) { - file->scaledTimeRange.start = std::max(static_cast(0), context.scaledTimeRange->start); - file->scaledTimeRange.end = std::min(file->duration(), context.scaledTimeRange->end); - } - file->_tagLevel = context.tagLevel; - file->timeStretchMode = context.timeStretchMode; - file->fileAttributes = context.fileAttributes; - file->path = filePath; - return file; + if (context.scaledTimeRange != nullptr) { + file->scaledTimeRange.start = std::max(static_cast(0), context.scaledTimeRange->start); + file->scaledTimeRange.end = std::min(file->duration(), context.scaledTimeRange->end); + } + file->_tagLevel = context.tagLevel; + file->timeStretchMode = context.timeStretchMode; + file->fileAttributes = context.fileAttributes; + file->path = filePath; + return file; } std::unique_ptr Codec::Encode(std::shared_ptr file) { - return Codec::Encode(file, nullptr); + return Codec::Encode(file, nullptr); } std::unique_ptr Codec::Encode(std::shared_ptr file, std::shared_ptr performanceData) { - CodecContext context = {}; - EncodeStream bodyBytes(&context); - WriteTagsOfFile(&bodyBytes, file.get(), performanceData.get()); + CodecContext context = {}; + EncodeStream bodyBytes(&context); + WriteTagsOfFile(&bodyBytes, file.get(), performanceData.get()); - EncodeStream fileBytes(&context); - fileBytes.writeInt8('P'); - fileBytes.writeInt8('A'); - fileBytes.writeInt8('G'); - fileBytes.writeUint8(Version); - fileBytes.writeUint32(bodyBytes.length()); - fileBytes.writeInt8(CompressionAlgorithm::UNCOMPRESSED); - fileBytes.writeBytes(&bodyBytes); - return fileBytes.release(); + EncodeStream fileBytes(&context); + fileBytes.writeInt8('P'); + fileBytes.writeInt8('A'); + fileBytes.writeInt8('G'); + fileBytes.writeUint8(Version); + fileBytes.writeUint32(bodyBytes.length()); + fileBytes.writeInt8(CompressionAlgorithm::UNCOMPRESSED); + fileBytes.writeBytes(&bodyBytes); + return fileBytes.release(); } std::shared_ptr Codec::ReadPerformanceData(const void* bytes, - uint32_t byteLength) { - CodecContext context = {}; - DecodeStream stream(&context, reinterpret_cast(bytes), byteLength); - auto bodyBytes = ReadBodyBytes(&stream); - if (context.hasException()) { - return nullptr; - } - auto header = ReadTagHeader(&bodyBytes); - if (context.hasException()) { - return nullptr; - } - - while (header.code != TagCode::End) { - auto tagBytes = bodyBytes.readBytes(header.length); - if (header.code == TagCode::Performance) { - auto data = std::shared_ptr(new PerformanceData()); - ReadPerformanceTag(&tagBytes, data.get()); - return data; + uint32_t byteLength) { + CodecContext context = {}; + DecodeStream stream(&context, reinterpret_cast(bytes), byteLength); + auto bodyBytes = ReadBodyBytes(&stream); + if (context.hasException()) { + return nullptr; } - header = ReadTagHeader(&bodyBytes); + auto header = ReadTagHeader(&bodyBytes); if (context.hasException()) { - return nullptr; + return nullptr; } - } - return nullptr; + + while (header.code != TagCode::End) { + auto tagBytes = bodyBytes.readBytes(header.length); + if (header.code == TagCode::Performance) { + auto data = std::shared_ptr(new PerformanceData()); + ReadPerformanceTag(&tagBytes, data.get()); + return data; + } + header = ReadTagHeader(&bodyBytes); + if (context.hasException()) { + return nullptr; + } + } + return nullptr; } } // namespace pag diff --git a/src/codec/CodecContext.cpp b/src/codec/CodecContext.cpp index ac37ca1abf..ee9aa71720 100644 --- a/src/codec/CodecContext.cpp +++ b/src/codec/CodecContext.cpp @@ -20,69 +20,69 @@ namespace pag { CodecContext::~CodecContext() { - for (auto& font : fontIDMap) { - delete font.second; - } - fontIDMap.clear(); - for (auto& font : fontNameMap) { - delete font.second; - } - fontNameMap.clear(); - for (auto composition : compositions) { - delete composition; - } - compositions.clear(); - for (auto image : images) { - delete image; - } - images.clear(); - errorMessages.clear(); - delete scaledTimeRange; + for (auto& font : fontIDMap) { + delete font.second; + } + fontIDMap.clear(); + for (auto& font : fontNameMap) { + delete font.second; + } + fontNameMap.clear(); + for (auto composition : compositions) { + delete composition; + } + compositions.clear(); + for (auto image : images) { + delete image; + } + images.clear(); + errorMessages.clear(); + delete scaledTimeRange; } FontData CodecContext::getFontData(int id) { - auto result = fontIDMap.find(id); - if (result != fontIDMap.end()) { - auto font = result->second; - return {font->fontFamily, font->fontStyle}; - } - return FontData("", ""); + auto result = fontIDMap.find(id); + if (result != fontIDMap.end()) { + auto font = result->second; + return {font->fontFamily, font->fontStyle}; + } + return FontData("", ""); } ImageBytes* CodecContext::getImageBytes(pag::ID imageID) { - for (auto image : images) { - if (image->id == imageID) { - return image; + for (auto image : images) { + if (image->id == imageID) { + return image; + } } - } - for (auto image : images) { - if (image->fileBytes == nullptr) { - return image; + for (auto image : images) { + if (image->fileBytes == nullptr) { + return image; + } } - } - auto image = new ImageBytes(); - images.push_back(image); - return image; + auto image = new ImageBytes(); + images.push_back(image); + return image; } std::vector CodecContext::releaseCompositions() { - auto compositions = this->compositions; - this->compositions.clear(); - return compositions; + auto compositions = this->compositions; + this->compositions.clear(); + return compositions; } std::vector CodecContext::releaseImages() { - auto images = this->images; - this->images.clear(); - return images; + auto images = this->images; + this->images.clear(); + return images; } uint32_t CodecContext::getFontID(const std::string& fontFamily, const std::string& fontStyle) { - auto result = fontNameMap.find(fontFamily + " - " + fontStyle); - if (result != fontNameMap.end()) { - return result->second->id; - } - return 0; + auto result = fontNameMap.find(fontFamily + " - " + fontStyle); + if (result != fontNameMap.end()) { + return result->second->id; + } + return 0; } } // namespace pag \ No newline at end of file diff --git a/src/codec/CodecContext.h b/src/codec/CodecContext.h index d1521e7906..cb73d4024d 100644 --- a/src/codec/CodecContext.h +++ b/src/codec/CodecContext.h @@ -24,28 +24,28 @@ namespace pag { struct FontDescriptor { - uint32_t id; - std::string fontFamily; - std::string fontStyle; + uint32_t id; + std::string fontFamily; + std::string fontStyle; }; class CodecContext : public StreamContext { - public: - ~CodecContext() override; - uint32_t getFontID(const std::string& fontFamily, const std::string& fontStyle); - FontData getFontData(int id); - ImageBytes* getImageBytes(ID imageID); - std::vector releaseCompositions(); - std::vector releaseImages(); +public: + ~CodecContext() override; + uint32_t getFontID(const std::string& fontFamily, const std::string& fontStyle); + FontData getFontData(int id); + ImageBytes* getImageBytes(ID imageID); + std::vector releaseCompositions(); + std::vector releaseImages(); - std::vector errorMessages; - std::unordered_map fontNameMap; - std::unordered_map fontIDMap; - std::vector compositions; - std::vector images; - int timeStretchMode = PAGTimeStretchMode::Repeat; - TimeRange* scaledTimeRange = nullptr; - FileAttributes fileAttributes = {}; - uint16_t tagLevel = 0; + std::vector errorMessages; + std::unordered_map fontNameMap; + std::unordered_map fontIDMap; + std::vector compositions; + std::vector images; + int timeStretchMode = PAGTimeStretchMode::Repeat; + TimeRange* scaledTimeRange = nullptr; + FileAttributes fileAttributes = {}; + uint16_t tagLevel = 0; }; } // namespace pag diff --git a/src/codec/DataTypes.cpp b/src/codec/DataTypes.cpp index 2adc2d85e4..a020f73865 100644 --- a/src/codec/DataTypes.cpp +++ b/src/codec/DataTypes.cpp @@ -24,468 +24,472 @@ namespace pag { class PathRecord { - public: - static const Enum Close = 0; - static const Enum Move = 1; - static const Enum Line = 2; - static const Enum HLine = 3; - static const Enum VLine = 4; - static const Enum Curve01 = 5; // has only control2 point - static const Enum Curve10 = 6; // has only control1 point - static const Enum Curve11 = 7; // has both control points +public: + static const Enum Close = 0; + static const Enum Move = 1; + static const Enum Line = 2; + static const Enum HLine = 3; + static const Enum VLine = 4; + static const Enum Curve01 = 5; // has only control2 point + static const Enum Curve10 = 6; // has only control1 point + static const Enum Curve11 = 7; // has both control points }; Ratio ReadRatio(DecodeStream* stream) { - Ratio ratio = {}; - ratio.numerator = stream->readEncodedInt32(); - ratio.denominator = stream->readEncodedUint32(); - return ratio; + Ratio ratio = {}; + ratio.numerator = stream->readEncodedInt32(); + ratio.denominator = stream->readEncodedUint32(); + return ratio; } Color ReadColor(DecodeStream* stream) { - Color color = {}; - color.red = stream->readUint8(); - color.green = stream->readUint8(); - color.blue = stream->readUint8(); - return color; + Color color = {}; + color.red = stream->readUint8(); + color.green = stream->readUint8(); + color.blue = stream->readUint8(); + return color; } Frame ReadTime(DecodeStream* stream) { - return static_cast(stream->readEncodedUint64()); + return static_cast(stream->readEncodedUint64()); } float ReadFloat(DecodeStream* stream) { - return stream->readFloat(); + return stream->readFloat(); } bool ReadBoolean(DecodeStream* stream) { - return stream->readBoolean(); + return stream->readBoolean(); } Enum ReadEnum(DecodeStream* stream) { - return stream->readUint8(); + return stream->readUint8(); } ID ReadID(DecodeStream* stream) { - return stream->readEncodedUint32(); + return stream->readEncodedUint32(); } Layer* ReadLayerID(DecodeStream* stream) { - auto id = stream->readEncodedUint32(); - if (id > 0) { - auto layer = new Layer(); - layer->id = id; - return layer; - } - return nullptr; + auto id = stream->readEncodedUint32(); + if (id > 0) { + auto layer = new Layer(); + layer->id = id; + return layer; + } + return nullptr; } MaskData* ReadMaskID(DecodeStream* stream) { - auto id = stream->readEncodedUint32(); - if (id > 0) { - auto mask = new MaskData(); - mask->id = id; - return mask; - } - return nullptr; + auto id = stream->readEncodedUint32(); + if (id > 0) { + auto mask = new MaskData(); + mask->id = id; + return mask; + } + return nullptr; } Composition* ReadCompositionID(DecodeStream* stream) { - auto id = stream->readEncodedUint32(); - if (id > 0) { - auto composition = new Composition(); - composition->id = id; - return composition; - } - return nullptr; + auto id = stream->readEncodedUint32(); + if (id > 0) { + auto composition = new Composition(); + composition->id = id; + return composition; + } + return nullptr; } std::string ReadString(DecodeStream* stream) { - return stream->readUTF8String(); + return stream->readUTF8String(); } Opacity ReadOpacity(DecodeStream* stream) { - return stream->readUint8(); + return stream->readUint8(); } Point ReadPoint(DecodeStream* stream) { - Point point = {}; - point.x = stream->readFloat(); - point.y = stream->readFloat(); - return point; + Point point = {}; + point.x = stream->readFloat(); + point.y = stream->readFloat(); + return point; } static void ReadPathInternal(DecodeStream* stream, PathData* value, const Enum records[], int64_t numVerbs) { - auto numBits = stream->readNumBits(); - float lastX = 0; - float lastY = 0; - auto& verbs = value->verbs; - auto& points = value->points; - for (uint32_t i = 0; i < numVerbs; i++) { - auto pathRecord = records[i]; - switch (pathRecord) { - case PathRecord::Close: - verbs.push_back(PathDataVerb::Close); - break; - case PathRecord::Move: - verbs.push_back(PathDataVerb::MoveTo); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - case PathRecord::Line: - verbs.push_back(PathDataVerb::LineTo); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - case PathRecord::HLine: - verbs.push_back(PathDataVerb::LineTo); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - case PathRecord::VLine: - verbs.push_back(PathDataVerb::LineTo); - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - case PathRecord::Curve01: - verbs.push_back(PathDataVerb::CurveTo); - points.push_back({lastX, lastY}); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - case PathRecord::Curve10: - verbs.push_back(PathDataVerb::CurveTo); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - points.push_back({lastX, lastY}); - break; - case PathRecord::Curve11: - verbs.push_back(PathDataVerb::CurveTo); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - lastX = stream->readBits(numBits) * SPATIAL_PRECISION; - lastY = stream->readBits(numBits) * SPATIAL_PRECISION; - points.push_back({lastX, lastY}); - break; - default: - break; + auto numBits = stream->readNumBits(); + float lastX = 0; + float lastY = 0; + auto& verbs = value->verbs; + auto& points = value->points; + for (uint32_t i = 0; i < numVerbs; i++) { + auto pathRecord = records[i]; + switch (pathRecord) { + case PathRecord::Close: + verbs.push_back(PathDataVerb::Close); + break; + case PathRecord::Move: + verbs.push_back(PathDataVerb::MoveTo); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + case PathRecord::Line: + verbs.push_back(PathDataVerb::LineTo); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + case PathRecord::HLine: + verbs.push_back(PathDataVerb::LineTo); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + case PathRecord::VLine: + verbs.push_back(PathDataVerb::LineTo); + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + case PathRecord::Curve01: + verbs.push_back(PathDataVerb::CurveTo); + points.push_back({lastX, lastY}); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + case PathRecord::Curve10: + verbs.push_back(PathDataVerb::CurveTo); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + points.push_back({lastX, lastY}); + break; + case PathRecord::Curve11: + verbs.push_back(PathDataVerb::CurveTo); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + lastX = stream->readBits(numBits) * SPATIAL_PRECISION; + lastY = stream->readBits(numBits) * SPATIAL_PRECISION; + points.push_back({lastX, lastY}); + break; + default: + break; + } } - } } PathHandle ReadPath(DecodeStream* stream) { - auto value = new PathData(); - int64_t numVerbs = stream->readEncodedUint32(); - if (numVerbs == 0) { + auto value = new PathData(); + int64_t numVerbs = stream->readEncodedUint32(); + if (numVerbs == 0) { + return PathHandle(value); + } + auto records = new Enum[static_cast(numVerbs)]; + for (uint32_t i = 0; i < numVerbs; i++) { + records[i] = static_cast(stream->readUBits(3)); + } + ReadPathInternal(stream, value, records, numVerbs); + delete[] records; return PathHandle(value); - } - auto records = new Enum[static_cast(numVerbs)]; - for (uint32_t i = 0; i < numVerbs; i++) { - records[i] = static_cast(stream->readUBits(3)); - } - ReadPathInternal(stream, value, records, numVerbs); - delete[] records; - return PathHandle(value); } void ReadFontData(DecodeStream* stream, void* target) { - auto textDocument = reinterpret_cast(target); - auto fontID = stream->readEncodedUint32(); - auto font = static_cast(stream->context)->getFontData(fontID); - textDocument->fontFamily = font.fontFamily; - textDocument->fontStyle = font.fontStyle; + auto textDocument = reinterpret_cast(target); + auto fontID = stream->readEncodedUint32(); + auto font = static_cast(stream->context)->getFontData(fontID); + textDocument->fontFamily = font.fontFamily; + textDocument->fontStyle = font.fontStyle; } bool WriteFontData(EncodeStream* stream, void* target) { - auto textDocument = reinterpret_cast(target); - auto id = static_cast(stream->context) - ->getFontID(textDocument->fontFamily, textDocument->fontStyle); - stream->writeEncodedUint32(id); - return true; + auto textDocument = reinterpret_cast(target); + auto id = static_cast(stream->context) + ->getFontID(textDocument->fontFamily, textDocument->fontStyle); + stream->writeEncodedUint32(id); + return true; } static std::unique_ptr TextDocumentBlockCore(TextDocument* textDocument, - TagCode tagCode) { - auto blockConfig = new BlockConfig(); - AddAttribute(blockConfig, &textDocument->applyFill, AttributeType::BitFlag, true); - AddAttribute(blockConfig, &textDocument->applyStroke, AttributeType::BitFlag, false); - AddAttribute(blockConfig, &textDocument->boxText, AttributeType::BitFlag, false); - AddAttribute(blockConfig, &textDocument->fauxBold, AttributeType::BitFlag, false); - AddAttribute(blockConfig, &textDocument->fauxItalic, AttributeType::BitFlag, false); - AddAttribute(blockConfig, &textDocument->strokeOverFill, AttributeType::BitFlag, true); - AddAttribute(blockConfig, &textDocument->baselineShift, AttributeType::Value, 0.0f); - AddAttribute(blockConfig, &textDocument->firstBaseLine, AttributeType::Value, 0.0f); - AddAttribute(blockConfig, &textDocument->boxTextPos, AttributeType::Value, Point::Zero()); - AddAttribute(blockConfig, &textDocument->boxTextSize, AttributeType::Value, Point::Zero()); - AddAttribute(blockConfig, &textDocument->fillColor, AttributeType::Value, Black); - AddAttribute(blockConfig, &textDocument->fontSize, AttributeType::Value, 24.0f); - AddAttribute(blockConfig, &textDocument->strokeColor, AttributeType::Value, Black); - AddAttribute(blockConfig, &textDocument->strokeWidth, AttributeType::Value, 1.0f); - AddAttribute(blockConfig, &textDocument->text, AttributeType::Value, std::string()); - AddAttribute(blockConfig, &textDocument->justification, AttributeType::Value, - ParagraphJustification::LeftJustify); - AddAttribute(blockConfig, &textDocument->leading, AttributeType::Value, 0.0f); - AddAttribute(blockConfig, &textDocument->tracking, AttributeType::Value, 0.0f); - if (tagCode >= TagCode::TextSourceV2) { - AddAttribute(blockConfig, &textDocument->backgroundColor, AttributeType::Value, White); - AddAttribute(blockConfig, &textDocument->backgroundAlpha, AttributeType::Value, Opaque); - } - if (tagCode >= TagCode::TextSourceV3) { - AddAttribute(blockConfig, &textDocument->direction, AttributeType::Value, - TextDirection::Vertical); - } - AddCustomAttribute(blockConfig, textDocument, ReadFontData, WriteFontData); - return std::unique_ptr(blockConfig); + TagCode tagCode) { + auto blockConfig = new BlockConfig(); + AddAttribute(blockConfig, &textDocument->applyFill, AttributeType::BitFlag, true); + AddAttribute(blockConfig, &textDocument->applyStroke, AttributeType::BitFlag, false); + AddAttribute(blockConfig, &textDocument->boxText, AttributeType::BitFlag, false); + AddAttribute(blockConfig, &textDocument->fauxBold, AttributeType::BitFlag, false); + AddAttribute(blockConfig, &textDocument->fauxItalic, AttributeType::BitFlag, false); + AddAttribute(blockConfig, &textDocument->strokeOverFill, AttributeType::BitFlag, true); + AddAttribute(blockConfig, &textDocument->baselineShift, AttributeType::Value, 0.0f); + AddAttribute(blockConfig, &textDocument->firstBaseLine, AttributeType::Value, 0.0f); + AddAttribute(blockConfig, &textDocument->boxTextPos, AttributeType::Value, Point::Zero()); + AddAttribute(blockConfig, &textDocument->boxTextSize, AttributeType::Value, Point::Zero()); + AddAttribute(blockConfig, &textDocument->fillColor, AttributeType::Value, Black); + AddAttribute(blockConfig, &textDocument->fontSize, AttributeType::Value, 24.0f); + AddAttribute(blockConfig, &textDocument->strokeColor, AttributeType::Value, Black); + AddAttribute(blockConfig, &textDocument->strokeWidth, AttributeType::Value, 1.0f); + AddAttribute(blockConfig, &textDocument->text, AttributeType::Value, std::string()); + AddAttribute(blockConfig, &textDocument->justification, AttributeType::Value, + ParagraphJustification::LeftJustify); + AddAttribute(blockConfig, &textDocument->leading, AttributeType::Value, 0.0f); + AddAttribute(blockConfig, &textDocument->tracking, AttributeType::Value, 0.0f); + if (tagCode >= TagCode::TextSourceV2) { + AddAttribute(blockConfig, &textDocument->backgroundColor, AttributeType::Value, White); + AddAttribute(blockConfig, &textDocument->backgroundAlpha, AttributeType::Value, Opaque); + } + if (tagCode >= TagCode::TextSourceV3) { + AddAttribute(blockConfig, &textDocument->direction, AttributeType::Value, + TextDirection::Vertical); + } + AddCustomAttribute(blockConfig, textDocument, ReadFontData, WriteFontData); + return std::unique_ptr(blockConfig); } static std::unique_ptr TextDocumentBlock(TextDocument* textDocument) { - return TextDocumentBlockCore(textDocument, TagCode::TextSource); + return TextDocumentBlockCore(textDocument, TagCode::TextSource); } static std::unique_ptr TextDocumentBlockV2(TextDocument* textDocument) { - return TextDocumentBlockCore(textDocument, TagCode::TextSourceV2); + return TextDocumentBlockCore(textDocument, TagCode::TextSourceV2); } static std::unique_ptr TextDocumentBlockV3(TextDocument* textDocument) { - return TextDocumentBlockCore(textDocument, TagCode::TextSourceV3); + return TextDocumentBlockCore(textDocument, TagCode::TextSourceV3); } TextDocumentHandle ReadTextDocument(DecodeStream* stream) { - auto value = new TextDocument(); - ReadBlock(stream, value, TextDocumentBlock); - return TextDocumentHandle(value); + auto value = new TextDocument(); + ReadBlock(stream, value, TextDocumentBlock); + return TextDocumentHandle(value); } TextDocumentHandle ReadTextDocumentV2(DecodeStream* stream) { - auto value = new TextDocument(); - ReadBlock(stream, value, TextDocumentBlockV2); - return TextDocumentHandle(value); + auto value = new TextDocument(); + ReadBlock(stream, value, TextDocumentBlockV2); + return TextDocumentHandle(value); } TextDocumentHandle ReadTextDocumentV3(DecodeStream* stream) { - auto value = new TextDocument(); - ReadBlock(stream, value, TextDocumentBlockV3); - return TextDocumentHandle(value); + auto value = new TextDocument(); + ReadBlock(stream, value, TextDocumentBlockV3); + return TextDocumentHandle(value); } GradientColorHandle ReadGradientColor(DecodeStream* stream) { - auto value = new GradientColor(); - auto& alphaStops = value->alphaStops; - auto& colorStops = value->colorStops; - auto alphaCount = stream->readEncodedUint32(); - auto colorCount = stream->readEncodedUint32(); - for (uint32_t i = 0; i < alphaCount; i++) { - AlphaStop stop = {}; - stop.position = stream->readUint16() * GRADIENT_PRECISION; - stop.midpoint = stream->readUint16() * GRADIENT_PRECISION; - stop.opacity = stream->readUint8(); - alphaStops.push_back(stop); - } - for (uint32_t i = 0; i < colorCount; i++) { - ColorStop stop = {}; - stop.position = stream->readUint16() * GRADIENT_PRECISION; - stop.midpoint = stream->readUint16() * GRADIENT_PRECISION; - stop.color = ReadColor(stream); - colorStops.push_back(stop); - } - std::sort(alphaStops.begin(), alphaStops.end(), - [](const AlphaStop& a, const AlphaStop& b) { return a.position < b.position; }); - std::sort(colorStops.begin(), colorStops.end(), - [](const ColorStop& a, const ColorStop& b) { return a.position < b.position; }); - return GradientColorHandle(value); + auto value = new GradientColor(); + auto& alphaStops = value->alphaStops; + auto& colorStops = value->colorStops; + auto alphaCount = stream->readEncodedUint32(); + auto colorCount = stream->readEncodedUint32(); + for (uint32_t i = 0; i < alphaCount; i++) { + AlphaStop stop = {}; + stop.position = stream->readUint16() * GRADIENT_PRECISION; + stop.midpoint = stream->readUint16() * GRADIENT_PRECISION; + stop.opacity = stream->readUint8(); + alphaStops.push_back(stop); + } + for (uint32_t i = 0; i < colorCount; i++) { + ColorStop stop = {}; + stop.position = stream->readUint16() * GRADIENT_PRECISION; + stop.midpoint = stream->readUint16() * GRADIENT_PRECISION; + stop.color = ReadColor(stream); + colorStops.push_back(stop); + } + std::sort(alphaStops.begin(), alphaStops.end(), + [](const AlphaStop& a, const AlphaStop& b) { + return a.position < b.position; + }); + std::sort(colorStops.begin(), colorStops.end(), + [](const ColorStop& a, const ColorStop& b) { + return a.position < b.position; + }); + return GradientColorHandle(value); } void WriteRatio(EncodeStream* stream, const Ratio& ratio) { - stream->writeEncodedInt32(ratio.numerator); - stream->writeEncodedUint32(ratio.denominator); + stream->writeEncodedInt32(ratio.numerator); + stream->writeEncodedUint32(ratio.denominator); } void WriteTime(EncodeStream* stream, Frame time) { - // Since most of the time values are positive (time in keyframes), - // just write it as uint64_t to save space (no need to write the sign bit). - // If it is negative time, it is also can be written and read as normal, but - // requires more space. - stream->writeEncodedUint64(static_cast(time)); + // Since most of the time values are positive (time in keyframes), + // just write it as uint64_t to save space (no need to write the sign bit). + // If it is negative time, it is also can be written and read as normal, but + // requires more space. + stream->writeEncodedUint64(static_cast(time)); } void WriteColor(EncodeStream* stream, const Color& color) { - stream->writeUint8(color.red); - stream->writeUint8(color.green); - stream->writeUint8(color.blue); + stream->writeUint8(color.red); + stream->writeUint8(color.green); + stream->writeUint8(color.blue); } void WriteFloat(EncodeStream* stream, float value) { - stream->writeFloat(value); + stream->writeFloat(value); } void WriteBoolean(EncodeStream* stream, bool value) { - stream->writeBoolean(value); + stream->writeBoolean(value); } void WriteEnum(EncodeStream* stream, Enum value) { - stream->writeUint8(value); + stream->writeUint8(value); } void WriteID(EncodeStream* stream, pag::ID value) { - stream->writeEncodedUint32(value); + stream->writeEncodedUint32(value); } void WriteLayerID(EncodeStream* stream, Layer* layer) { - if (layer != nullptr) { - stream->writeEncodedUint32(layer->id); - } else { - stream->writeEncodedUint32(0); - } + if (layer != nullptr) { + stream->writeEncodedUint32(layer->id); + } else { + stream->writeEncodedUint32(0); + } } void WriteMaskID(EncodeStream* stream, MaskData* mask) { - if (mask != nullptr) { - stream->writeEncodedUint32(mask->id); - } else { - stream->writeEncodedUint32(0); - } + if (mask != nullptr) { + stream->writeEncodedUint32(mask->id); + } else { + stream->writeEncodedUint32(0); + } } void WriteCompositionID(EncodeStream* stream, Composition* composition) { - if (composition != nullptr) { - stream->writeEncodedUint32(composition->id); - } else { - stream->writeEncodedUint32(0); - } + if (composition != nullptr) { + stream->writeEncodedUint32(composition->id); + } else { + stream->writeEncodedUint32(0); + } } void WriteString(EncodeStream* stream, std::string value) { - stream->writeUTF8String(value); + stream->writeUTF8String(value); } void WriteOpacity(EncodeStream* stream, pag::Opacity value) { - stream->writeUint8(value); + stream->writeUint8(value); } void WritePoint(EncodeStream* stream, pag::Point value) { - stream->writeFloat(value.x); - stream->writeFloat(value.y); + stream->writeFloat(value.x); + stream->writeFloat(value.y); } static void WritePathInternal(EncodeStream* stream, pag::PathHandle value) { - auto& points = value->points; - std::vector pointList; - uint32_t index = 0; - auto lastPoint = Point::Make(0, 0); - Point control1{}, control2{}, point{}; - for (auto& verb : value->verbs) { - switch (verb) { - case PathDataVerb::Close: - stream->writeUBits(PathRecord::Close, 3); - break; - case PathDataVerb::MoveTo: - lastPoint = points[index++]; - stream->writeUBits(PathRecord::Move, 3); - pointList.push_back(lastPoint.x); - pointList.push_back(lastPoint.y); - break; - case PathDataVerb::LineTo: - point = points[index++]; - if (point.x == lastPoint.x) { - stream->writeUBits(PathRecord::VLine, 3); - pointList.push_back(point.y); - } else if (point.y == lastPoint.y) { - stream->writeUBits(PathRecord::HLine, 3); - pointList.push_back(point.x); - } else { - stream->writeUBits(PathRecord::Line, 3); - pointList.push_back(point.x); - pointList.push_back(point.y); + auto& points = value->points; + std::vector pointList; + uint32_t index = 0; + auto lastPoint = Point::Make(0, 0); + Point control1{}, control2{}, point{}; + for (auto& verb : value->verbs) { + switch (verb) { + case PathDataVerb::Close: + stream->writeUBits(PathRecord::Close, 3); + break; + case PathDataVerb::MoveTo: + lastPoint = points[index++]; + stream->writeUBits(PathRecord::Move, 3); + pointList.push_back(lastPoint.x); + pointList.push_back(lastPoint.y); + break; + case PathDataVerb::LineTo: + point = points[index++]; + if (point.x == lastPoint.x) { + stream->writeUBits(PathRecord::VLine, 3); + pointList.push_back(point.y); + } else if (point.y == lastPoint.y) { + stream->writeUBits(PathRecord::HLine, 3); + pointList.push_back(point.x); + } else { + stream->writeUBits(PathRecord::Line, 3); + pointList.push_back(point.x); + pointList.push_back(point.y); + } + lastPoint = point; + break; + case PathDataVerb::CurveTo: + control1 = points[index++]; + control2 = points[index++]; + point = points[index++]; + if (control1 == lastPoint) { + stream->writeUBits(PathRecord::Curve01, 3); + pointList.push_back(control2.x); + pointList.push_back(control2.y); + pointList.push_back(point.x); + pointList.push_back(point.y); + lastPoint = point; + } else if (control2 == point) { + stream->writeUBits(PathRecord::Curve10, 3); + pointList.push_back(control1.x); + pointList.push_back(control1.y); + pointList.push_back(point.x); + pointList.push_back(point.y); + lastPoint = point; + } else { + stream->writeUBits(PathRecord::Curve11, 3); + pointList.push_back(control1.x); + pointList.push_back(control1.y); + pointList.push_back(control2.x); + pointList.push_back(control2.y); + pointList.push_back(point.x); + pointList.push_back(point.y); + lastPoint = point; + } + break; } - lastPoint = point; - break; - case PathDataVerb::CurveTo: - control1 = points[index++]; - control2 = points[index++]; - point = points[index++]; - if (control1 == lastPoint) { - stream->writeUBits(PathRecord::Curve01, 3); - pointList.push_back(control2.x); - pointList.push_back(control2.y); - pointList.push_back(point.x); - pointList.push_back(point.y); - lastPoint = point; - } else if (control2 == point) { - stream->writeUBits(PathRecord::Curve10, 3); - pointList.push_back(control1.x); - pointList.push_back(control1.y); - pointList.push_back(point.x); - pointList.push_back(point.y); - lastPoint = point; - } else { - stream->writeUBits(PathRecord::Curve11, 3); - pointList.push_back(control1.x); - pointList.push_back(control1.y); - pointList.push_back(control2.x); - pointList.push_back(control2.y); - pointList.push_back(point.x); - pointList.push_back(point.y); - lastPoint = point; - } - break; } - } - stream->writeFloatList(&pointList[0], static_cast(pointList.size()), SPATIAL_PRECISION); + stream->writeFloatList(&pointList[0], static_cast(pointList.size()), SPATIAL_PRECISION); } void WritePath(EncodeStream* stream, pag::PathHandle value) { - stream->writeEncodedUint32(static_cast(value->verbs.size())); - if (value->verbs.empty()) { - return; - } - WritePathInternal(stream, value); + stream->writeEncodedUint32(static_cast(value->verbs.size())); + if (value->verbs.empty()) { + return; + } + WritePathInternal(stream, value); } void WriteTextDocument(EncodeStream* stream, pag::TextDocumentHandle value) { - WriteBlock(stream, value.get(), TextDocumentBlock); + WriteBlock(stream, value.get(), TextDocumentBlock); } void WriteTextDocumentV2(EncodeStream* stream, pag::TextDocumentHandle value) { - WriteBlock(stream, value.get(), TextDocumentBlockV2); + WriteBlock(stream, value.get(), TextDocumentBlockV2); } void WriteTextDocumentV3(EncodeStream* stream, pag::TextDocumentHandle value) { - WriteBlock(stream, value.get(), TextDocumentBlockV3); + WriteBlock(stream, value.get(), TextDocumentBlockV3); } void WriteGradientColor(EncodeStream* stream, pag::GradientColorHandle value) { - auto& alphaStops = value->alphaStops; - auto& colorStops = value->colorStops; - auto alphaCount = static_cast(alphaStops.size()); - auto colorCount = static_cast(colorStops.size()); - stream->writeEncodedUint32(alphaCount); - stream->writeEncodedUint32(colorCount); - for (uint32_t i = 0; i < alphaCount; i++) { - auto& stop = alphaStops[i]; - stream->writeUint16(static_cast(stop.position / GRADIENT_PRECISION)); - stream->writeUint16(static_cast(stop.midpoint / GRADIENT_PRECISION)); - stream->writeUint8(stop.opacity); - } - for (uint32_t i = 0; i < colorCount; i++) { - auto& stop = colorStops[i]; - stream->writeUint16(static_cast(stop.position / GRADIENT_PRECISION)); - stream->writeUint16(static_cast(stop.midpoint / GRADIENT_PRECISION)); - WriteColor(stream, stop.color); - } + auto& alphaStops = value->alphaStops; + auto& colorStops = value->colorStops; + auto alphaCount = static_cast(alphaStops.size()); + auto colorCount = static_cast(colorStops.size()); + stream->writeEncodedUint32(alphaCount); + stream->writeEncodedUint32(colorCount); + for (uint32_t i = 0; i < alphaCount; i++) { + auto& stop = alphaStops[i]; + stream->writeUint16(static_cast(stop.position / GRADIENT_PRECISION)); + stream->writeUint16(static_cast(stop.midpoint / GRADIENT_PRECISION)); + stream->writeUint8(stop.opacity); + } + for (uint32_t i = 0; i < colorCount; i++) { + auto& stop = colorStops[i]; + stream->writeUint16(static_cast(stop.position / GRADIENT_PRECISION)); + stream->writeUint16(static_cast(stop.midpoint / GRADIENT_PRECISION)); + WriteColor(stream, stop.color); + } } } // namespace pag diff --git a/src/codec/NALUType.h b/src/codec/NALUType.h index 4c9b0ffdba..fc5e639ead 100644 --- a/src/codec/NALUType.h +++ b/src/codec/NALUType.h @@ -20,7 +20,7 @@ namespace pag { enum class NALUType { - AnnexB, - AVCC, + AnnexB, + AVCC, }; } // namespace pag diff --git a/src/codec/TagHeader.cpp b/src/codec/TagHeader.cpp index 39a65612bb..7b22637e79 100644 --- a/src/codec/TagHeader.cpp +++ b/src/codec/TagHeader.cpp @@ -21,35 +21,35 @@ namespace pag { TagHeader ReadTagHeader(DecodeStream* stream) { - auto codeAndLength = stream->readUint16(); - uint32_t length = codeAndLength & static_cast(63); - uint16_t code = codeAndLength >> 6; - if (length == 63) { - length = stream->readUint32(); - } - auto context = static_cast(stream->context); - if (context->tagLevel < code) { - context->tagLevel = code; - } - TagHeader header = {static_cast(code), length}; - return header; + auto codeAndLength = stream->readUint16(); + uint32_t length = codeAndLength & static_cast(63); + uint16_t code = codeAndLength >> 6; + if (length == 63) { + length = stream->readUint32(); + } + auto context = static_cast(stream->context); + if (context->tagLevel < code) { + context->tagLevel = code; + } + TagHeader header = {static_cast(code), length}; + return header; } void WriteTagHeader(EncodeStream* stream, EncodeStream* tagBytes, TagCode code) { - auto length = tagBytes->length(); - uint16_t typeAndLength = static_cast(code) << 6; - if (length < 63) { - typeAndLength = typeAndLength | static_cast(length); - stream->writeUint16(typeAndLength); - } else { - typeAndLength = typeAndLength | static_cast(63); - stream->writeUint16(typeAndLength); - stream->writeUint32(length); - } - stream->writeBytes(tagBytes); + auto length = tagBytes->length(); + uint16_t typeAndLength = static_cast(code) << 6; + if (length < 63) { + typeAndLength = typeAndLength | static_cast(length); + stream->writeUint16(typeAndLength); + } else { + typeAndLength = typeAndLength | static_cast(63); + stream->writeUint16(typeAndLength); + stream->writeUint32(length); + } + stream->writeBytes(tagBytes); } void WriteEndTag(EncodeStream* stream) { - stream->writeUint16(0); + stream->writeUint16(0); } } // namespace pag \ No newline at end of file diff --git a/src/codec/TagHeader.h b/src/codec/TagHeader.h index 8eabae0842..87073bdd6a 100644 --- a/src/codec/TagHeader.h +++ b/src/codec/TagHeader.h @@ -24,29 +24,29 @@ namespace pag { struct TagHeader { - TagCode code; - uint32_t length; + TagCode code; + uint32_t length; }; TagHeader ReadTagHeader(DecodeStream* stream); template void ReadTags(DecodeStream* stream, T parameter, void (*reader)(DecodeStream*, TagCode, T)) { - auto header = ReadTagHeader(stream); - if (stream->context->hasException()) { - return; - } - while (header.code != TagCode::End) { - auto tagBytes = stream->readBytes(header.length); - reader(&tagBytes, header.code, parameter); + auto header = ReadTagHeader(stream); if (stream->context->hasException()) { - return; + return; } - header = ReadTagHeader(stream); - if (stream->context->hasException()) { - return; + while (header.code != TagCode::End) { + auto tagBytes = stream->readBytes(header.length); + reader(&tagBytes, header.code, parameter); + if (stream->context->hasException()) { + return; + } + header = ReadTagHeader(stream); + if (stream->context->hasException()) { + return; + } } - } } void WriteTagHeader(EncodeStream* stream, EncodeStream* tagBytes, TagCode code); @@ -55,8 +55,8 @@ void WriteEndTag(EncodeStream* stream); template void WriteTag(EncodeStream* stream, T parameter, TagCode (*writer)(EncodeStream*, T)) { - EncodeStream bytes(stream->context); - auto code = writer(&bytes, parameter); - WriteTagHeader(stream, &bytes, code); + EncodeStream bytes(stream->context); + auto code = writer(&bytes, parameter); + WriteTagHeader(stream, &bytes, code); } } // namespace pag diff --git a/src/codec/tags/AudioBytes.cpp b/src/codec/tags/AudioBytes.cpp index 7ade2b0b3a..98e77fc513 100644 --- a/src/codec/tags/AudioBytes.cpp +++ b/src/codec/tags/AudioBytes.cpp @@ -20,13 +20,13 @@ namespace pag { void ReadAudioBytes(DecodeStream* stream, Composition* composition) { - composition->audioBytes = stream->readByteData().release(); - composition->audioStartTime = ReadTime(stream); + composition->audioBytes = stream->readByteData().release(); + composition->audioStartTime = ReadTime(stream); } TagCode WriteAudioBytes(EncodeStream* stream, Composition* composition) { - stream->writeByteData(composition->audioBytes); - WriteTime(stream, composition->audioStartTime); - return TagCode::AudioBytes; + stream->writeByteData(composition->audioBytes); + WriteTime(stream, composition->audioStartTime); + return TagCode::AudioBytes; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/BitmapCompositionTag.cpp b/src/codec/tags/BitmapCompositionTag.cpp index 4299aa0dff..d3be161be9 100644 --- a/src/codec/tags/BitmapCompositionTag.cpp +++ b/src/codec/tags/BitmapCompositionTag.cpp @@ -26,38 +26,39 @@ namespace pag { void ReadTagsOfBitmapComposition(DecodeStream* stream, TagCode code, BitmapComposition* composition) { - switch (code) { + switch (code) { case TagCode::BitmapSequence: { - auto sequence = ReadBitmapSequence(stream); - sequence->composition = composition; - composition->sequences.push_back(sequence); - } break; + auto sequence = ReadBitmapSequence(stream); + sequence->composition = composition; + composition->sequences.push_back(sequence); + } + break; default: - ReadTagsOfComposition(stream, code, composition); - break; - } + ReadTagsOfComposition(stream, code, composition); + break; + } } BitmapComposition* ReadBitmapComposition(DecodeStream* stream) { - auto composition = new BitmapComposition(); - composition->id = stream->readEncodedUint32(); - ReadTags(stream, composition, ReadTagsOfBitmapComposition); - return composition; + auto composition = new BitmapComposition(); + composition->id = stream->readEncodedUint32(); + ReadTags(stream, composition, ReadTagsOfBitmapComposition); + return composition; } static bool lessFirst(const BitmapSequence* item1, const BitmapSequence* item2) { - return item1->width < item2->width; + return item1->width < item2->width; } TagCode WriteBitmapComposition(EncodeStream* stream, BitmapComposition* composition) { - stream->writeEncodedUint32(composition->id); - WriteTagsOfComposition(stream, composition); - auto sequences = composition->sequences; - std::sort(sequences.begin(), sequences.end(), lessFirst); - for (auto sequence : sequences) { - WriteTag(stream, sequence, WriteBitmapSequence); - } - WriteEndTag(stream); - return TagCode::BitmapCompositionBlock; + stream->writeEncodedUint32(composition->id); + WriteTagsOfComposition(stream, composition); + auto sequences = composition->sequences; + std::sort(sequences.begin(), sequences.end(), lessFirst); + for (auto sequence : sequences) { + WriteTag(stream, sequence, WriteBitmapSequence); + } + WriteEndTag(stream); + return TagCode::BitmapCompositionBlock; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/BitmapSequence.cpp b/src/codec/tags/BitmapSequence.cpp index d83b6e28f1..57b0e823e4 100644 --- a/src/codec/tags/BitmapSequence.cpp +++ b/src/codec/tags/BitmapSequence.cpp @@ -20,59 +20,59 @@ namespace pag { BitmapSequence* ReadBitmapSequence(DecodeStream* stream) { - auto sequence = new BitmapSequence(); - sequence->width = stream->readEncodedInt32(); - sequence->height = stream->readEncodedInt32(); - sequence->frameRate = stream->readFloat(); - auto count = stream->readEncodedUint32(); - for (uint32_t i = 0; i < count; i++) { - auto bitmapFrame = new BitmapFrame(); - sequence->frames.push_back(bitmapFrame); - bitmapFrame->isKeyframe = stream->readBitBoolean(); - } - for (uint32_t i = 0; i < count; i++) { - auto bitmapFrame = sequence->frames[i]; - uint32_t bitmapCount = stream->readEncodedUint32(); - for (uint32_t j = 0; j < bitmapCount; j++) { - auto bitmap = new BitmapRect(); - bitmapFrame->bitmaps.push_back(bitmap); - bitmap->x = stream->readEncodedInt32(); - bitmap->y = stream->readEncodedInt32(); - bitmap->fileBytes = stream->readByteData().release(); + auto sequence = new BitmapSequence(); + sequence->width = stream->readEncodedInt32(); + sequence->height = stream->readEncodedInt32(); + sequence->frameRate = stream->readFloat(); + auto count = stream->readEncodedUint32(); + for (uint32_t i = 0; i < count; i++) { + auto bitmapFrame = new BitmapFrame(); + sequence->frames.push_back(bitmapFrame); + bitmapFrame->isKeyframe = stream->readBitBoolean(); } - } - return sequence; + for (uint32_t i = 0; i < count; i++) { + auto bitmapFrame = sequence->frames[i]; + uint32_t bitmapCount = stream->readEncodedUint32(); + for (uint32_t j = 0; j < bitmapCount; j++) { + auto bitmap = new BitmapRect(); + bitmapFrame->bitmaps.push_back(bitmap); + bitmap->x = stream->readEncodedInt32(); + bitmap->y = stream->readEncodedInt32(); + bitmap->fileBytes = stream->readByteData().release(); + } + } + return sequence; } TagCode WriteBitmapSequence(EncodeStream* stream, BitmapSequence* sequence) { - stream->writeEncodedInt32(sequence->width); - stream->writeEncodedInt32(sequence->height); - stream->writeFloat(sequence->frameRate); - auto count = static_cast(sequence->frames.size()); - stream->writeEncodedUint32(count); - for (uint32_t i = 0; i < count; i++) { - stream->writeBitBoolean(sequence->frames[i]->isKeyframe); - } - for (uint32_t i = 0; i < count; i++) { - auto bitmapFrame = sequence->frames[i]; - uint32_t bitmapCount = 0; - for (auto bitmap : bitmapFrame->bitmaps) { - if (bitmap->fileBytes->length() == 0) { - continue; - } - bitmapCount++; + stream->writeEncodedInt32(sequence->width); + stream->writeEncodedInt32(sequence->height); + stream->writeFloat(sequence->frameRate); + auto count = static_cast(sequence->frames.size()); + stream->writeEncodedUint32(count); + for (uint32_t i = 0; i < count; i++) { + stream->writeBitBoolean(sequence->frames[i]->isKeyframe); } - stream->writeEncodedUint32(bitmapCount); - for (auto bitmap : bitmapFrame->bitmaps) { - auto fileBytes = bitmap->fileBytes; - if (fileBytes->length() == 0) { - continue; - } - stream->writeEncodedInt32(bitmap->x); - stream->writeEncodedInt32(bitmap->y); - stream->writeByteData(fileBytes); + for (uint32_t i = 0; i < count; i++) { + auto bitmapFrame = sequence->frames[i]; + uint32_t bitmapCount = 0; + for (auto bitmap : bitmapFrame->bitmaps) { + if (bitmap->fileBytes->length() == 0) { + continue; + } + bitmapCount++; + } + stream->writeEncodedUint32(bitmapCount); + for (auto bitmap : bitmapFrame->bitmaps) { + auto fileBytes = bitmap->fileBytes; + if (fileBytes->length() == 0) { + continue; + } + stream->writeEncodedInt32(bitmap->x); + stream->writeEncodedInt32(bitmap->y); + stream->writeByteData(fileBytes); + } } - } - return TagCode::BitmapSequence; + return TagCode::BitmapSequence; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/CachePolicy.cpp b/src/codec/tags/CachePolicy.cpp index e8b4fa6f57..ee16b23b9c 100644 --- a/src/codec/tags/CachePolicy.cpp +++ b/src/codec/tags/CachePolicy.cpp @@ -20,11 +20,11 @@ namespace pag { void ReadCachePolicy(DecodeStream* stream, Layer* layer) { - layer->cachePolicy = ReadEnum(stream); + layer->cachePolicy = ReadEnum(stream); } TagCode WriteCachePolicy(EncodeStream* stream, Layer* layer) { - WriteEnum(stream, layer->cachePolicy); - return TagCode::CachePolicy; + WriteEnum(stream, layer->cachePolicy); + return TagCode::CachePolicy; } }; // namespace pag \ No newline at end of file diff --git a/src/codec/tags/CompositionAttributes.cpp b/src/codec/tags/CompositionAttributes.cpp index 87cfc187a5..a3a8a71984 100644 --- a/src/codec/tags/CompositionAttributes.cpp +++ b/src/codec/tags/CompositionAttributes.cpp @@ -20,19 +20,19 @@ namespace pag { void ReadCompositionAttributes(DecodeStream* stream, Composition* composition) { - composition->width = stream->readEncodedInt32(); - composition->height = stream->readEncodedInt32(); - composition->duration = ReadTime(stream); - composition->frameRate = stream->readFloat(); - composition->backgroundColor = ReadColor(stream); + composition->width = stream->readEncodedInt32(); + composition->height = stream->readEncodedInt32(); + composition->duration = ReadTime(stream); + composition->frameRate = stream->readFloat(); + composition->backgroundColor = ReadColor(stream); } TagCode WriteCompositionAttributes(EncodeStream* stream, Composition* composition) { - stream->writeEncodedInt32(composition->width); - stream->writeEncodedInt32(composition->height); - WriteTime(stream, composition->duration); - stream->writeFloat(composition->frameRate); - WriteColor(stream, composition->backgroundColor); - return TagCode::CompositionAttributes; + stream->writeEncodedInt32(composition->width); + stream->writeEncodedInt32(composition->height); + WriteTime(stream, composition->duration); + stream->writeFloat(composition->frameRate); + WriteColor(stream, composition->backgroundColor); + return TagCode::CompositionAttributes; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/CompositionReference.cpp b/src/codec/tags/CompositionReference.cpp index ed34b108cf..e01de68a13 100644 --- a/src/codec/tags/CompositionReference.cpp +++ b/src/codec/tags/CompositionReference.cpp @@ -20,18 +20,18 @@ namespace pag { void ReadCompositionReference(DecodeStream* stream, PreComposeLayer* layer) { - auto id = stream->readEncodedUint32(); - if (id > 0) { - layer->composition = new Composition(); - layer->composition->id = id; - } - layer->compositionStartTime = ReadTime(stream); + auto id = stream->readEncodedUint32(); + if (id > 0) { + layer->composition = new Composition(); + layer->composition->id = id; + } + layer->compositionStartTime = ReadTime(stream); } TagCode WriteCompositionReference(EncodeStream* stream, PreComposeLayer* layer) { - auto id = layer->composition != nullptr ? layer->composition->id : static_cast(0); - stream->writeEncodedUint32(id); - WriteTime(stream, layer->compositionStartTime); - return TagCode::CompositionReference; + auto id = layer->composition != nullptr ? layer->composition->id : static_cast(0); + stream->writeEncodedUint32(id); + WriteTime(stream, layer->compositionStartTime); + return TagCode::CompositionReference; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/CompositionTag.cpp b/src/codec/tags/CompositionTag.cpp index 940b4f3aee..67b8977d07 100644 --- a/src/codec/tags/CompositionTag.cpp +++ b/src/codec/tags/CompositionTag.cpp @@ -22,28 +22,28 @@ namespace pag { void ReadTagsOfComposition(DecodeStream* stream, TagCode code, Composition* composition) { - switch (code) { + switch (code) { case TagCode::CompositionAttributes: - ReadCompositionAttributes(stream, composition); - break; + ReadCompositionAttributes(stream, composition); + break; case TagCode::AudioBytes: - ReadAudioBytes(stream, composition); - break; + ReadAudioBytes(stream, composition); + break; case TagCode::MarkerList: - ReadMarkerList(stream, &composition->audioMarkers); - break; + ReadMarkerList(stream, &composition->audioMarkers); + break; default: - break; - } + break; + } } void WriteTagsOfComposition(EncodeStream* stream, Composition* composition) { - WriteTag(stream, composition, WriteCompositionAttributes); - if (composition->audioBytes != nullptr) { - WriteTag(stream, composition, WriteAudioBytes); - if (!composition->audioMarkers.empty()) { - WriteTag(stream, &composition->audioMarkers, WriteMarkerList); + WriteTag(stream, composition, WriteCompositionAttributes); + if (composition->audioBytes != nullptr) { + WriteTag(stream, composition, WriteAudioBytes); + if (!composition->audioMarkers.empty()) { + WriteTag(stream, &composition->audioMarkers, WriteMarkerList); + } } - } } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/EffectTag.cpp b/src/codec/tags/EffectTag.cpp index 56ebf3dbd0..7477557946 100644 --- a/src/codec/tags/EffectTag.cpp +++ b/src/codec/tags/EffectTag.cpp @@ -29,79 +29,79 @@ namespace pag { bool ReadEffect(DecodeStream* stream, TagCode code, Layer* layer) { - Effect* effect = nullptr; - switch (code) { + Effect* effect = nullptr; + switch (code) { case TagCode::MotionTileEffect: - effect = ReadTagBlock(stream, MotionTileEffectTag); - break; + effect = ReadTagBlock(stream, MotionTileEffectTag); + break; case TagCode::LevelsIndividualEffect: - effect = ReadTagBlock(stream, LevelsIndividualEffectTag); - break; + effect = ReadTagBlock(stream, LevelsIndividualEffectTag); + break; case TagCode::CornerPinEffect: - effect = ReadTagBlock(stream, CornerPinEffectTag); - break; + effect = ReadTagBlock(stream, CornerPinEffectTag); + break; case TagCode::BulgeEffect: - effect = ReadTagBlock(stream, BulgeEffectTag); - break; + effect = ReadTagBlock(stream, BulgeEffectTag); + break; case TagCode::FastBlurEffect: - effect = ReadTagBlock(stream, FastBlurEffectTag); - break; + effect = ReadTagBlock(stream, FastBlurEffectTag); + break; case TagCode::GlowEffect: - effect = ReadTagBlock(stream, GlowEffectTag); - break; + effect = ReadTagBlock(stream, GlowEffectTag); + break; case TagCode::DisplacementMapEffect: - effect = ReadTagBlock(stream, DisplacementMapEffectTag); - break; + effect = ReadTagBlock(stream, DisplacementMapEffectTag); + break; case TagCode::RadialBlurEffect: - effect = ReadTagBlock(stream, RadialBlurEffectTag); - break; + effect = ReadTagBlock(stream, RadialBlurEffectTag); + break; case TagCode::MosaicEffect: - effect = ReadTagBlock(stream, MosaicEffectTag); - break; + effect = ReadTagBlock(stream, MosaicEffectTag); + break; default: - break; - } - if (effect) { - layer->effects.push_back(effect); - } - return effect != nullptr; + break; + } + if (effect) { + layer->effects.push_back(effect); + } + return effect != nullptr; } void WriteEffects(EncodeStream* stream, const std::vector& effects) { - for (auto& effect : effects) { - switch (effect->type()) { - case EffectType::MotionTile: - WriteTagBlock(stream, static_cast(effect), MotionTileEffectTag); - break; - case EffectType::LevelsIndividual: - WriteTagBlock(stream, static_cast(effect), - LevelsIndividualEffectTag); - break; - case EffectType::CornerPin: - WriteTagBlock(stream, static_cast(effect), CornerPinEffectTag); - break; - case EffectType::Bulge: - WriteTagBlock(stream, static_cast(effect), BulgeEffectTag); - break; - case EffectType::FastBlur: - WriteTagBlock(stream, static_cast(effect), FastBlurEffectTag); - break; - case EffectType::Glow: - WriteTagBlock(stream, static_cast(effect), GlowEffectTag); - break; - case EffectType::DisplacementMap: - WriteTagBlock(stream, static_cast(effect), - DisplacementMapEffectTag); - break; - case EffectType::RadialBlur: - WriteTagBlock(stream, static_cast(effect), RadialBlurEffectTag); - break; - case EffectType::Mosaic: - WriteTagBlock(stream, static_cast(effect), MosaicEffectTag); - break; - default: - break; + for (auto& effect : effects) { + switch (effect->type()) { + case EffectType::MotionTile: + WriteTagBlock(stream, static_cast(effect), MotionTileEffectTag); + break; + case EffectType::LevelsIndividual: + WriteTagBlock(stream, static_cast(effect), + LevelsIndividualEffectTag); + break; + case EffectType::CornerPin: + WriteTagBlock(stream, static_cast(effect), CornerPinEffectTag); + break; + case EffectType::Bulge: + WriteTagBlock(stream, static_cast(effect), BulgeEffectTag); + break; + case EffectType::FastBlur: + WriteTagBlock(stream, static_cast(effect), FastBlurEffectTag); + break; + case EffectType::Glow: + WriteTagBlock(stream, static_cast(effect), GlowEffectTag); + break; + case EffectType::DisplacementMap: + WriteTagBlock(stream, static_cast(effect), + DisplacementMapEffectTag); + break; + case EffectType::RadialBlur: + WriteTagBlock(stream, static_cast(effect), RadialBlurEffectTag); + break; + case EffectType::Mosaic: + WriteTagBlock(stream, static_cast(effect), MosaicEffectTag); + break; + default: + break; + } } - } } } // namespace pag diff --git a/src/codec/tags/FileAttributes.cpp b/src/codec/tags/FileAttributes.cpp index d01febc723..082be795eb 100644 --- a/src/codec/tags/FileAttributes.cpp +++ b/src/codec/tags/FileAttributes.cpp @@ -21,33 +21,33 @@ namespace pag { void ReadFileAttributes(DecodeStream* stream, pag::FileAttributes* fileAttributes) { - fileAttributes->timestamp = stream->readEncodedInt64(); - fileAttributes->pluginVersion = stream->readUTF8String(); - fileAttributes->aeVersion = stream->readUTF8String(); - fileAttributes->systemVersion = stream->readUTF8String(); - fileAttributes->author = stream->readUTF8String(); - fileAttributes->scene = stream->readUTF8String(); + fileAttributes->timestamp = stream->readEncodedInt64(); + fileAttributes->pluginVersion = stream->readUTF8String(); + fileAttributes->aeVersion = stream->readUTF8String(); + fileAttributes->systemVersion = stream->readUTF8String(); + fileAttributes->author = stream->readUTF8String(); + fileAttributes->scene = stream->readUTF8String(); - auto warningCount = static_cast(stream->readEncodedUint32()); - for (int i = 0; i < warningCount; i++) { - auto warning = stream->readUTF8String(); - fileAttributes->warnings.push_back(warning); - } + auto warningCount = static_cast(stream->readEncodedUint32()); + for (int i = 0; i < warningCount; i++) { + auto warning = stream->readUTF8String(); + fileAttributes->warnings.push_back(warning); + } } TagCode WriteFileAttributes(EncodeStream* stream, pag::FileAttributes* fileAttributes) { - stream->writeEncodedInt64(fileAttributes->timestamp); - stream->writeUTF8String(fileAttributes->pluginVersion); - stream->writeUTF8String(fileAttributes->aeVersion); - stream->writeUTF8String(fileAttributes->systemVersion); - stream->writeUTF8String(fileAttributes->author); - stream->writeUTF8String(fileAttributes->scene); + stream->writeEncodedInt64(fileAttributes->timestamp); + stream->writeUTF8String(fileAttributes->pluginVersion); + stream->writeUTF8String(fileAttributes->aeVersion); + stream->writeUTF8String(fileAttributes->systemVersion); + stream->writeUTF8String(fileAttributes->author); + stream->writeUTF8String(fileAttributes->scene); - stream->writeEncodedUint32(static_cast(fileAttributes->warnings.size())); - for (auto& warning : fileAttributes->warnings) { - stream->writeUTF8String(warning); - } + stream->writeEncodedUint32(static_cast(fileAttributes->warnings.size())); + for (auto& warning : fileAttributes->warnings) { + stream->writeUTF8String(warning); + } - return TagCode::FileAttributes; + return TagCode::FileAttributes; } } // namespace pag diff --git a/src/codec/tags/FileTags.cpp b/src/codec/tags/FileTags.cpp index 38040a317f..a6e73612ad 100644 --- a/src/codec/tags/FileTags.cpp +++ b/src/codec/tags/FileTags.cpp @@ -30,49 +30,49 @@ namespace pag { static void ReadTag_FontTables(DecodeStream* stream, CodecContext*) { - ReadFontTables(stream); + ReadFontTables(stream); } static void ReadTag_FileAttributes(DecodeStream* stream, CodecContext* context) { - ReadFileAttributes(stream, &(context->fileAttributes)); + ReadFileAttributes(stream, &(context->fileAttributes)); } static void ReadTag_TimeStretchMode(DecodeStream* stream, CodecContext* context) { - ReadTimeStretchMode(stream, context); + ReadTimeStretchMode(stream, context); } static void ReadTag_ImageTables(DecodeStream* stream, CodecContext* context) { - ReadImageTables(stream, &(context->images)); + ReadImageTables(stream, &(context->images)); } static void ReadTag_ImageBytes(DecodeStream* stream, CodecContext* context) { - auto imageBytes = ReadImageBytes(stream); - context->images.push_back(imageBytes); + auto imageBytes = ReadImageBytes(stream); + context->images.push_back(imageBytes); } static void ReadTag_ImageBytesV2(DecodeStream* stream, CodecContext* context) { - auto imageBytes = ReadImageBytesV2(stream); - context->images.push_back(imageBytes); + auto imageBytes = ReadImageBytesV2(stream); + context->images.push_back(imageBytes); } static void ReadTag_ImageBytesV3(DecodeStream* stream, CodecContext* context) { - auto imageBytes = ReadImageBytesV3(stream); - context->images.push_back(imageBytes); + auto imageBytes = ReadImageBytesV3(stream); + context->images.push_back(imageBytes); } static void ReadTag_VectorCompositionBlock(DecodeStream* stream, CodecContext* context) { - auto composition = ReadVectorComposition(stream); - context->compositions.push_back(composition); + auto composition = ReadVectorComposition(stream); + context->compositions.push_back(composition); } static void ReadTag_BitmapCompositionBlock(DecodeStream* stream, CodecContext* context) { - auto composition = ReadBitmapComposition(stream); - context->compositions.push_back(composition); + auto composition = ReadBitmapComposition(stream); + context->compositions.push_back(composition); } static void ReadTag_VideoCompositionBlock(DecodeStream* stream, CodecContext* context) { - auto composition = ReadVideoComposition(stream); - context->compositions.push_back(composition); + auto composition = ReadVideoComposition(stream); + context->compositions.push_back(composition); } using ReadTagHandler = void(DecodeStream* stream, CodecContext* context); @@ -90,84 +90,84 @@ static const std::unordered_map, EnumClas }; void ReadTagsOfFile(DecodeStream* stream, TagCode code, CodecContext* context) { - auto iter = handlers.find(code); - if (iter != handlers.end()) { - iter->second(stream, context); - } + auto iter = handlers.find(code); + if (iter != handlers.end()) { + iter->second(stream, context); + } } void GetFontFromTextDocument(std::vector& fontList, std::unordered_set& fontSet, const TextDocumentHandle& textDocument) { - if (textDocument == nullptr) { - return; - } - auto key = textDocument->fontFamily + "|" + textDocument->fontStyle; - if (fontSet.count(key) > 0) { - return; - } - fontSet.insert(key); - fontList.emplace_back(textDocument->fontFamily, textDocument->fontStyle); + if (textDocument == nullptr) { + return; + } + auto key = textDocument->fontFamily + "|" + textDocument->fontStyle; + if (fontSet.count(key) > 0) { + return; + } + fontSet.insert(key); + fontList.emplace_back(textDocument->fontFamily, textDocument->fontStyle); } std::vector GetFontList(std::vector compositions) { - std::vector fontList; - std::unordered_set fontSet; - for (auto& composition : compositions) { - if (composition->type() != CompositionType::Vector) { - continue; - } - for (auto& layer : reinterpret_cast(composition)->layers) { - if (layer->type() != LayerType::Text) { - continue; - } - auto textLayer = reinterpret_cast(layer); - if (textLayer->sourceText->animatable()) { - auto keyframes = - reinterpret_cast*>(textLayer->sourceText) - ->keyframes; - GetFontFromTextDocument(fontList, fontSet, keyframes[0]->startValue); - for (auto& keyframe : keyframes) { - GetFontFromTextDocument(fontList, fontSet, keyframe->endValue); + std::vector fontList; + std::unordered_set fontSet; + for (auto& composition : compositions) { + if (composition->type() != CompositionType::Vector) { + continue; + } + for (auto& layer : reinterpret_cast(composition)->layers) { + if (layer->type() != LayerType::Text) { + continue; + } + auto textLayer = reinterpret_cast(layer); + if (textLayer->sourceText->animatable()) { + auto keyframes = + reinterpret_cast*>(textLayer->sourceText) + ->keyframes; + GetFontFromTextDocument(fontList, fontSet, keyframes[0]->startValue); + for (auto& keyframe : keyframes) { + GetFontFromTextDocument(fontList, fontSet, keyframe->endValue); + } + } else { + GetFontFromTextDocument(fontList, fontSet, textLayer->sourceText->getValueAt(0)); + } } - } else { - GetFontFromTextDocument(fontList, fontSet, textLayer->sourceText->getValueAt(0)); - } } - } - return fontList; + return fontList; } static void WriteComposition(EncodeStream* stream, Composition* composition) { - if (composition->type() == CompositionType::Vector) { - WriteTag(stream, static_cast(composition), WriteVectorComposition); - } else if (composition->type() == CompositionType::Bitmap) { - WriteTag(stream, static_cast(composition), WriteBitmapComposition); - } else if (composition->type() == CompositionType::Video) { - WriteTag(stream, static_cast(composition), WriteVideoComposition); - } + if (composition->type() == CompositionType::Vector) { + WriteTag(stream, static_cast(composition), WriteVectorComposition); + } else if (composition->type() == CompositionType::Bitmap) { + WriteTag(stream, static_cast(composition), WriteBitmapComposition); + } else if (composition->type() == CompositionType::Video) { + WriteTag(stream, static_cast(composition), WriteVideoComposition); + } } void WriteTagsOfFile(EncodeStream* stream, const File* file, PerformanceData* performanceData) { - if (performanceData != nullptr) { - WriteTag(stream, performanceData, WritePerformanceTag); - } - auto fileAttributes = file->fileAttributes; - if (!fileAttributes.empty()) { - WriteTag(stream, &fileAttributes, WriteFileAttributes); - } - if (file->timeStretchMode != PAGTimeStretchMode::Repeat || file->hasScaledTimeRange()) { - WriteTag(stream, file, WriteTimeStretchMode); - } - auto fontList = GetFontList(file->compositions); - if (!(fontList.empty())) { - WriteTag(stream, &fontList, WriteFontTables); - } - if (!file->images.empty()) { - WriteImages(stream, &(file->images)); - } - auto func = std::bind(WriteComposition, stream, std::placeholders::_1); - std::for_each(file->compositions.begin(), file->compositions.end(), func); - WriteEndTag(stream); + if (performanceData != nullptr) { + WriteTag(stream, performanceData, WritePerformanceTag); + } + auto fileAttributes = file->fileAttributes; + if (!fileAttributes.empty()) { + WriteTag(stream, &fileAttributes, WriteFileAttributes); + } + if (file->timeStretchMode != PAGTimeStretchMode::Repeat || file->hasScaledTimeRange()) { + WriteTag(stream, file, WriteTimeStretchMode); + } + auto fontList = GetFontList(file->compositions); + if (!(fontList.empty())) { + WriteTag(stream, &fontList, WriteFontTables); + } + if (!file->images.empty()) { + WriteImages(stream, &(file->images)); + } + auto func = std::bind(WriteComposition, stream, std::placeholders::_1); + std::for_each(file->compositions.begin(), file->compositions.end(), func); + WriteEndTag(stream); } } // namespace pag diff --git a/src/codec/tags/FontTables.cpp b/src/codec/tags/FontTables.cpp index 82578eb9cf..e71ff47f90 100644 --- a/src/codec/tags/FontTables.cpp +++ b/src/codec/tags/FontTables.cpp @@ -20,32 +20,32 @@ namespace pag { void ReadFontTables(DecodeStream* stream) { - auto count = stream->readEncodedUint32(); - auto context = static_cast(stream->context); - auto fontIDMap = &(context->fontIDMap); - for (uint32_t id = 0; id < count; id++) { - auto fontData = new FontDescriptor(); - fontData->id = id; - fontData->fontFamily = stream->readUTF8String(); - fontData->fontStyle = stream->readUTF8String(); - fontIDMap->insert(std::make_pair(id, fontData)); - } + auto count = stream->readEncodedUint32(); + auto context = static_cast(stream->context); + auto fontIDMap = &(context->fontIDMap); + for (uint32_t id = 0; id < count; id++) { + auto fontData = new FontDescriptor(); + fontData->id = id; + fontData->fontFamily = stream->readUTF8String(); + fontData->fontStyle = stream->readUTF8String(); + fontIDMap->insert(std::make_pair(id, fontData)); + } } TagCode WriteFontTables(EncodeStream* stream, std::vector* fontList) { - auto context = static_cast(stream->context); - auto fontNameMap = &(context->fontNameMap); - stream->writeEncodedUint32(static_cast(fontList->size())); - uint32_t id = 0; - for (auto& font : *fontList) { - stream->writeUTF8String(font.fontFamily); - stream->writeUTF8String(font.fontStyle); - auto fontData = new FontDescriptor(); - fontData->id = id++; - fontData->fontFamily = font.fontFamily; - fontData->fontStyle = font.fontStyle; - fontNameMap->insert(std::make_pair(font.fontFamily + " - " + font.fontStyle, fontData)); - } - return TagCode::FontTables; + auto context = static_cast(stream->context); + auto fontNameMap = &(context->fontNameMap); + stream->writeEncodedUint32(static_cast(fontList->size())); + uint32_t id = 0; + for (auto& font : *fontList) { + stream->writeUTF8String(font.fontFamily); + stream->writeUTF8String(font.fontStyle); + auto fontData = new FontDescriptor(); + fontData->id = id++; + fontData->fontFamily = font.fontFamily; + fontData->fontStyle = font.fontStyle; + fontNameMap->insert(std::make_pair(font.fontFamily + " - " + font.fontStyle, fontData)); + } + return TagCode::FontTables; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/ImageBytes.cpp b/src/codec/tags/ImageBytes.cpp index bad4982593..fe5303562c 100644 --- a/src/codec/tags/ImageBytes.cpp +++ b/src/codec/tags/ImageBytes.cpp @@ -22,22 +22,22 @@ namespace pag { ImageBytes* ReadImageBytes(DecodeStream* stream) { - auto imageBytes = new ImageBytes(); - imageBytes->id = stream->readEncodedUint32(); - imageBytes->fileBytes = stream->readByteData().release(); - if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + auto imageBytes = new ImageBytes(); + imageBytes->id = stream->readEncodedUint32(); + imageBytes->fileBytes = stream->readByteData().release(); + if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + return imageBytes; + } + if (!WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), + &imageBytes->width, &imageBytes->height)) { + LOGE("Get webP size fail."); + } return imageBytes; - } - if (!WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), - &imageBytes->width, &imageBytes->height)) { - LOGE("Get webP size fail."); - } - return imageBytes; } TagCode WriteImageBytes(EncodeStream* stream, pag::ImageBytes* imageBytes) { - stream->writeEncodedUint32(imageBytes->id); - stream->writeByteData(imageBytes->fileBytes); - return TagCode::ImageBytes; + stream->writeEncodedUint32(imageBytes->id); + stream->writeByteData(imageBytes->fileBytes); + return TagCode::ImageBytes; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/ImageBytesV2.cpp b/src/codec/tags/ImageBytesV2.cpp index 6125b80f55..f17d94195b 100644 --- a/src/codec/tags/ImageBytesV2.cpp +++ b/src/codec/tags/ImageBytesV2.cpp @@ -22,25 +22,25 @@ namespace pag { ImageBytes* ReadImageBytesV2(DecodeStream* stream) { - auto imageBytes = new ImageBytes(); - imageBytes->id = stream->readEncodedUint32(); - imageBytes->fileBytes = stream->readByteData().release(); - imageBytes->scaleFactor = stream->readFloat(); - int width; - int height; - if (WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), &width, - &height)) { - imageBytes->width = static_cast(round(width * 1.0 / imageBytes->scaleFactor)); - imageBytes->height = static_cast(round(height * 1.0 / imageBytes->scaleFactor)); - } else { - LOGE("Get webP size fail."); - } - return imageBytes; + auto imageBytes = new ImageBytes(); + imageBytes->id = stream->readEncodedUint32(); + imageBytes->fileBytes = stream->readByteData().release(); + imageBytes->scaleFactor = stream->readFloat(); + int width; + int height; + if (WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), &width, + &height)) { + imageBytes->width = static_cast(round(width * 1.0 / imageBytes->scaleFactor)); + imageBytes->height = static_cast(round(height * 1.0 / imageBytes->scaleFactor)); + } else { + LOGE("Get webP size fail."); + } + return imageBytes; } TagCode WriteImageBytesV2(EncodeStream* stream, pag::ImageBytes* imageBytes) { - WriteImageBytes(stream, imageBytes); - stream->writeFloat(imageBytes->scaleFactor); - return TagCode::ImageBytesV2; + WriteImageBytes(stream, imageBytes); + stream->writeFloat(imageBytes->scaleFactor); + return TagCode::ImageBytesV2; } } // namespace pag diff --git a/src/codec/tags/ImageBytesV3.cpp b/src/codec/tags/ImageBytesV3.cpp index fcabc4c2e6..880515b667 100644 --- a/src/codec/tags/ImageBytesV3.cpp +++ b/src/codec/tags/ImageBytesV3.cpp @@ -21,23 +21,23 @@ namespace pag { ImageBytes* ReadImageBytesV3(DecodeStream* stream) { - auto imageBytes = new ImageBytes(); - imageBytes->id = stream->readEncodedUint32(); - imageBytes->fileBytes = stream->readByteData().release(); - imageBytes->scaleFactor = stream->readFloat(); - imageBytes->width = stream->readEncodedInt32(); - imageBytes->height = stream->readEncodedInt32(); - imageBytes->anchorX = stream->readEncodedInt32(); - imageBytes->anchorY = stream->readEncodedInt32(); - return imageBytes; + auto imageBytes = new ImageBytes(); + imageBytes->id = stream->readEncodedUint32(); + imageBytes->fileBytes = stream->readByteData().release(); + imageBytes->scaleFactor = stream->readFloat(); + imageBytes->width = stream->readEncodedInt32(); + imageBytes->height = stream->readEncodedInt32(); + imageBytes->anchorX = stream->readEncodedInt32(); + imageBytes->anchorY = stream->readEncodedInt32(); + return imageBytes; } TagCode WriteImageBytesV3(EncodeStream* stream, pag::ImageBytes* imageBytes) { - WriteImageBytesV2(stream, imageBytes); - stream->writeEncodedInt32(imageBytes->width); - stream->writeEncodedInt32(imageBytes->height); - stream->writeEncodedInt32(imageBytes->anchorX); - stream->writeEncodedInt32(imageBytes->anchorY); - return TagCode::ImageBytesV3; + WriteImageBytesV2(stream, imageBytes); + stream->writeEncodedInt32(imageBytes->width); + stream->writeEncodedInt32(imageBytes->height); + stream->writeEncodedInt32(imageBytes->anchorX); + stream->writeEncodedInt32(imageBytes->anchorY); + return TagCode::ImageBytesV3; } } // namespace pag diff --git a/src/codec/tags/ImageFillRule.cpp b/src/codec/tags/ImageFillRule.cpp index f409ad2ca1..c5a939bd4d 100644 --- a/src/codec/tags/ImageFillRule.cpp +++ b/src/codec/tags/ImageFillRule.cpp @@ -22,52 +22,52 @@ namespace pag { static std::unique_ptr ImageFillRuleTag(ImageFillRule* imageFillRule, TagCode code) { - auto tagConfig = new BlockConfig(code); - AddAttribute(tagConfig, &imageFillRule->scaleMode, AttributeType::Value, PAGScaleMode::LetterBox); - AddAttribute(tagConfig, &imageFillRule->timeRemap, AttributeType::SimpleProperty, - static_cast(0)); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(code); + AddAttribute(tagConfig, &imageFillRule->scaleMode, AttributeType::Value, PAGScaleMode::LetterBox); + AddAttribute(tagConfig, &imageFillRule->timeRemap, AttributeType::SimpleProperty, + static_cast(0)); + return std::unique_ptr(tagConfig); } static std::unique_ptr ImageFillRuleTagV1(ImageFillRule* imageFillRule) { - return ImageFillRuleTag(imageFillRule, TagCode::ImageFillRule); + return ImageFillRuleTag(imageFillRule, TagCode::ImageFillRule); } static std::unique_ptr ImageFillRuleTagV2(ImageFillRule* imageFillRule) { - return ImageFillRuleTag(imageFillRule, TagCode::ImageFillRuleV2); + return ImageFillRuleTag(imageFillRule, TagCode::ImageFillRuleV2); } void ReadImageFillRule(pag::DecodeStream* stream, pag::ImageLayer* layer, TagCode code) { - layer->imageFillRule = new ImageFillRule(); + layer->imageFillRule = new ImageFillRule(); - if (code == TagCode::ImageFillRule) { - ReadTagBlock(stream, layer->imageFillRule, ImageFillRuleTagV1); + if (code == TagCode::ImageFillRule) { + ReadTagBlock(stream, layer->imageFillRule, ImageFillRuleTagV1); - // The interpolation type should be linear in v1 tag, but we store it as hold, so we need to fix - // it here. - auto timeRemap = layer->imageFillRule->timeRemap; - if (timeRemap != nullptr && timeRemap->animatable()) { - auto AnimatableTimeRemap = static_cast*>(timeRemap); - for (auto& keyFrame : AnimatableTimeRemap->keyframes) { - keyFrame->interpolationType = pag::KeyframeInterpolationType::Linear; - } + // The interpolation type should be linear in v1 tag, but we store it as hold, so we need to fix + // it here. + auto timeRemap = layer->imageFillRule->timeRemap; + if (timeRemap != nullptr && timeRemap->animatable()) { + auto AnimatableTimeRemap = static_cast*>(timeRemap); + for (auto& keyFrame : AnimatableTimeRemap->keyframes) { + keyFrame->interpolationType = pag::KeyframeInterpolationType::Linear; + } + } + } else { + ReadTagBlock(stream, layer->imageFillRule, ImageFillRuleTagV2); } - } else { - ReadTagBlock(stream, layer->imageFillRule, ImageFillRuleTagV2); - } } void WriteImageFillRule(pag::EncodeStream* stream, pag::ImageFillRule* imageFillRule) { - auto timeRemap = imageFillRule->timeRemap; - if (timeRemap != nullptr && timeRemap->animatable()) { - for (auto& keyFrame : static_cast*>(timeRemap)->keyframes) { - if (keyFrame->interpolationType != pag::KeyframeInterpolationType::Linear) { - WriteTagBlock(stream, imageFillRule, ImageFillRuleTagV2); - return; - } + auto timeRemap = imageFillRule->timeRemap; + if (timeRemap != nullptr && timeRemap->animatable()) { + for (auto& keyFrame : static_cast*>(timeRemap)->keyframes) { + if (keyFrame->interpolationType != pag::KeyframeInterpolationType::Linear) { + WriteTagBlock(stream, imageFillRule, ImageFillRuleTagV2); + return; + } + } } - } - WriteTagBlock(stream, imageFillRule, ImageFillRuleTagV1); + WriteTagBlock(stream, imageFillRule, ImageFillRuleTagV1); } } // namespace pag diff --git a/src/codec/tags/ImageReference.cpp b/src/codec/tags/ImageReference.cpp index f1c8fdd07a..145fc8b8c2 100644 --- a/src/codec/tags/ImageReference.cpp +++ b/src/codec/tags/ImageReference.cpp @@ -20,13 +20,13 @@ namespace pag { void ReadImageReference(DecodeStream* stream, ImageLayer* layer) { - auto id = stream->readEncodedUint32(); - auto context = static_cast(stream->context); - layer->imageBytes = context->getImageBytes(id); + auto id = stream->readEncodedUint32(); + auto context = static_cast(stream->context); + layer->imageBytes = context->getImageBytes(id); } TagCode WriteImageReference(EncodeStream* stream, ImageLayer* layer) { - stream->writeEncodedUint32(layer->imageBytes->id); - return TagCode::ImageReference; + stream->writeEncodedUint32(layer->imageBytes->id); + return TagCode::ImageReference; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/ImageTables.cpp b/src/codec/tags/ImageTables.cpp index 3e29954277..4f03f392ab 100644 --- a/src/codec/tags/ImageTables.cpp +++ b/src/codec/tags/ImageTables.cpp @@ -21,28 +21,28 @@ namespace pag { void ReadImageTables(DecodeStream* stream, std::vector* images) { - auto count = stream->readEncodedUint32(); - for (uint32_t i = 0; i < count; i++) { - auto imageBytes = ReadImageBytes(stream); - images->push_back(imageBytes); - } + auto count = stream->readEncodedUint32(); + for (uint32_t i = 0; i < count; i++) { + auto imageBytes = ReadImageBytes(stream); + images->push_back(imageBytes); + } } TagCode WriteImageTables(EncodeStream* stream, const std::vector* images) { - uint32_t imageCount = 0; - for (auto& imageBytes : *images) { - if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { - continue; + uint32_t imageCount = 0; + for (auto& imageBytes : *images) { + if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + continue; + } + imageCount++; } - imageCount++; - } - stream->writeEncodedUint32(imageCount); - for (auto& imageBytes : *images) { - if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { - continue; + stream->writeEncodedUint32(imageCount); + for (auto& imageBytes : *images) { + if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + continue; + } + WriteImageBytes(stream, imageBytes); } - WriteImageBytes(stream, imageBytes); - } - return TagCode::ImageTables; + return TagCode::ImageTables; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/Images.cpp b/src/codec/tags/Images.cpp index 9c590d67de..4194432941 100644 --- a/src/codec/tags/Images.cpp +++ b/src/codec/tags/Images.cpp @@ -21,49 +21,49 @@ namespace pag { static bool FindImage(const std::vector* images) { - bool found = false; - for (auto& imageBytes : *images) { - if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { - continue; + bool found = false; + for (auto& imageBytes : *images) { + if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + continue; + } + if ((imageBytes->width != 0 && imageBytes->height != 0) || imageBytes->scaleFactor != 1.0f) { + found = true; + break; + } } - if ((imageBytes->width != 0 && imageBytes->height != 0) || imageBytes->scaleFactor != 1.0f) { - found = true; - break; - } - } - return found; + return found; } void WriteImages(EncodeStream* stream, const std::vector* images) { - if (!FindImage(images)) { - WriteTag(stream, images, WriteImageTables); - return; - } - for (auto& imageBytes : *images) { - if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { - continue; + if (!FindImage(images)) { + WriteTag(stream, images, WriteImageTables); + return; } + for (auto& imageBytes : *images) { + if (imageBytes->fileBytes == nullptr || imageBytes->fileBytes->length() == 0) { + continue; + } - int scaledWidth = 0; - int scaledHeight = 0; - if (!WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), &scaledWidth, - &scaledHeight)) { - LOGE("Get webP size fail."); - continue; - } + int scaledWidth = 0; + int scaledHeight = 0; + if (!WebPGetInfo(imageBytes->fileBytes->data(), imageBytes->fileBytes->length(), &scaledWidth, + &scaledHeight)) { + LOGE("Get webP size fail."); + continue; + } - int realWidth = static_cast(ceil(imageBytes->width * imageBytes->scaleFactor)); - int realHeight = static_cast(ceil(imageBytes->height * imageBytes->scaleFactor)); + int realWidth = static_cast(ceil(imageBytes->width * imageBytes->scaleFactor)); + int realHeight = static_cast(ceil(imageBytes->height * imageBytes->scaleFactor)); - if (scaledWidth == realWidth && scaledHeight == realHeight) { - if (imageBytes->scaleFactor == 1.0f) { - WriteTag(stream, imageBytes, WriteImageBytes); - } else { - WriteTag(stream, imageBytes, WriteImageBytesV2); - } - } else { - WriteTag(stream, imageBytes, WriteImageBytesV3); + if (scaledWidth == realWidth && scaledHeight == realHeight) { + if (imageBytes->scaleFactor == 1.0f) { + WriteTag(stream, imageBytes, WriteImageBytes); + } else { + WriteTag(stream, imageBytes, WriteImageBytesV2); + } + } else { + WriteTag(stream, imageBytes, WriteImageBytesV3); + } } - } } } // namespace pag diff --git a/src/codec/tags/LayerAttributes.cpp b/src/codec/tags/LayerAttributes.cpp index d002823920..6f62edf0db 100644 --- a/src/codec/tags/LayerAttributes.cpp +++ b/src/codec/tags/LayerAttributes.cpp @@ -20,36 +20,36 @@ namespace pag { std::unique_ptr MakeFromLayerAttributesTag(TagCode tagCode, Layer* layer) { - auto tagConfig = new BlockConfig(tagCode); - AddAttribute(tagConfig, &layer->isActive, AttributeType::BitFlag, true); - AddAttribute(tagConfig, &layer->autoOrientation, AttributeType::BitFlag, false); - if (tagConfig->tagCode == TagCode::LayerAttributesV3) { - AddAttribute(tagConfig, &layer->motionBlur, AttributeType::BitFlag, false); - } - AddAttribute(tagConfig, &layer->parent, AttributeType::Value, static_cast(nullptr)); - AddAttribute(tagConfig, &layer->stretch, AttributeType::Value, DefaultRatio); - AddAttribute(tagConfig, &layer->startTime, AttributeType::Value, ZeroFrame); - AddAttribute(tagConfig, &layer->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &layer->trackMatteType, AttributeType::Value, TrackMatteType::None); - AddAttribute(tagConfig, &layer->timeRemap, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &layer->duration, AttributeType::FixedValue, ZeroFrame); - if (tagConfig->tagCode == TagCode::LayerAttributesV2 || - tagConfig->tagCode == TagCode::LayerAttributesV3) { - AddAttribute(tagConfig, &layer->name, AttributeType::Value, std::string("")); - } - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(tagCode); + AddAttribute(tagConfig, &layer->isActive, AttributeType::BitFlag, true); + AddAttribute(tagConfig, &layer->autoOrientation, AttributeType::BitFlag, false); + if (tagConfig->tagCode == TagCode::LayerAttributesV3) { + AddAttribute(tagConfig, &layer->motionBlur, AttributeType::BitFlag, false); + } + AddAttribute(tagConfig, &layer->parent, AttributeType::Value, static_cast(nullptr)); + AddAttribute(tagConfig, &layer->stretch, AttributeType::Value, DefaultRatio); + AddAttribute(tagConfig, &layer->startTime, AttributeType::Value, ZeroFrame); + AddAttribute(tagConfig, &layer->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &layer->trackMatteType, AttributeType::Value, TrackMatteType::None); + AddAttribute(tagConfig, &layer->timeRemap, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &layer->duration, AttributeType::FixedValue, ZeroFrame); + if (tagConfig->tagCode == TagCode::LayerAttributesV2 || + tagConfig->tagCode == TagCode::LayerAttributesV3) { + AddAttribute(tagConfig, &layer->name, AttributeType::Value, std::string("")); + } + return std::unique_ptr(tagConfig); } std::unique_ptr LayerAttributesTag(Layer* layer) { - return MakeFromLayerAttributesTag(TagCode::LayerAttributes, layer); + return MakeFromLayerAttributesTag(TagCode::LayerAttributes, layer); } std::unique_ptr LayerAttributesTagV2(Layer* layer) { - return MakeFromLayerAttributesTag(TagCode::LayerAttributesV2, layer); + return MakeFromLayerAttributesTag(TagCode::LayerAttributesV2, layer); } std::unique_ptr LayerAttributesTagV3(Layer* layer) { - return MakeFromLayerAttributesTag(TagCode::LayerAttributesV3, layer); + return MakeFromLayerAttributesTag(TagCode::LayerAttributesV3, layer); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/LayerAttributesExtra.cpp b/src/codec/tags/LayerAttributesExtra.cpp index 954265bb87..dba920d13b 100644 --- a/src/codec/tags/LayerAttributesExtra.cpp +++ b/src/codec/tags/LayerAttributesExtra.cpp @@ -20,9 +20,9 @@ namespace pag { std::unique_ptr LayerAttributesExtraTag(Layer* layer) { - auto tagConfig = new BlockConfig(TagCode::LayerAttributesExtra); - AddAttribute(tagConfig, &layer->name, AttributeType::Value, std::string("")); - AddAttribute(tagConfig, &layer->motionBlur, AttributeType::BitFlag, false); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::LayerAttributesExtra); + AddAttribute(tagConfig, &layer->name, AttributeType::Value, std::string("")); + AddAttribute(tagConfig, &layer->motionBlur, AttributeType::BitFlag, false); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/LayerStyleTag.cpp b/src/codec/tags/LayerStyleTag.cpp index b7a0038184..c09ab4ab31 100644 --- a/src/codec/tags/LayerStyleTag.cpp +++ b/src/codec/tags/LayerStyleTag.cpp @@ -22,44 +22,45 @@ namespace pag { bool ReadLayerStyles(DecodeStream* stream, TagCode code, Layer* layer) { - LayerStyle* style = nullptr; - switch (code) { + LayerStyle* style = nullptr; + switch (code) { case TagCode::DropShadowStyle: { - auto dropShadowStyle = ReadTagBlock(stream, DropShadowStyleTag); - dropShadowStyle->spread = new Property(); - dropShadowStyle->spread->value = 0.0f; // set default value - style = dropShadowStyle; - } break; + auto dropShadowStyle = ReadTagBlock(stream, DropShadowStyleTag); + dropShadowStyle->spread = new Property(); + dropShadowStyle->spread->value = 0.0f; // set default value + style = dropShadowStyle; + } + break; case TagCode::DropShadowStyleV2: - style = ReadTagBlock(stream, DropShadowStyleTagV2); - break; + style = ReadTagBlock(stream, DropShadowStyleTagV2); + break; default: - break; - } - if (style) { - layer->layerStyles.push_back(style); - } - return style != nullptr; + break; + } + if (style) { + layer->layerStyles.push_back(style); + } + return style != nullptr; } void WriteLayerStyles(EncodeStream* stream, const std::vector& layerStyles) { - for (auto& style : layerStyles) { - switch (style->type()) { - case LayerStyleType::DropShadow: { - auto spread = static_cast(style)->spread; - auto size = static_cast(style)->size; - if ((size != nullptr && size->animatable()) || - (spread != nullptr && - (spread->animatable() || spread->value != 0.0f))) { // if not default value - WriteTagBlock(stream, static_cast(style), DropShadowStyleTagV2); - } else { - WriteTagBlock(stream, static_cast(style), DropShadowStyleTag); + for (auto& style : layerStyles) { + switch (style->type()) { + case LayerStyleType::DropShadow: { + auto spread = static_cast(style)->spread; + auto size = static_cast(style)->size; + if ((size != nullptr && size->animatable()) || + (spread != nullptr && + (spread->animatable() || spread->value != 0.0f))) { // if not default value + WriteTagBlock(stream, static_cast(style), DropShadowStyleTagV2); + } else { + WriteTagBlock(stream, static_cast(style), DropShadowStyleTag); + } + break; + } + default: + break; } - break; - } - default: - break; } - } } } // namespace pag diff --git a/src/codec/tags/LayerTag.cpp b/src/codec/tags/LayerTag.cpp index ff8594f4e2..681e128eca 100644 --- a/src/codec/tags/LayerTag.cpp +++ b/src/codec/tags/LayerTag.cpp @@ -43,229 +43,234 @@ namespace pag { } void ReadTagsOfLayer(DecodeStream* stream, TagCode code, Layer* layer) { - switch (code) { + switch (code) { case TagCode::LayerAttributes: - ReadTagBlock(stream, layer, LayerAttributesTag); - if (layer->duration <= 0) { - layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from - // an old file format. - } - break; + ReadTagBlock(stream, layer, LayerAttributesTag); + if (layer->duration <= 0) { + layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from + // an old file format. + } + break; case TagCode::LayerAttributesV2: - ReadTagBlock(stream, layer, LayerAttributesTagV2); - if (layer->duration <= 0) { - layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from - // an old file format. - } - break; + ReadTagBlock(stream, layer, LayerAttributesTagV2); + if (layer->duration <= 0) { + layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from + // an old file format. + } + break; case TagCode::LayerAttributesV3: - ReadTagBlock(stream, layer, LayerAttributesTagV3); - if (layer->duration <= 0) { - layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from - // an old file format. - } - break; + ReadTagBlock(stream, layer, LayerAttributesTagV3); + if (layer->duration <= 0) { + layer->duration = 1; // The duration can not be zero, fix it when the value is parsed from + // an old file format. + } + break; case TagCode::LayerAttributesExtra: - ReadTagBlock(stream, layer, LayerAttributesExtraTag); - break; + ReadTagBlock(stream, layer, LayerAttributesExtraTag); + break; case TagCode::MaskBlock: { - auto mask = ReadTagBlock(stream, MaskTag); - layer->masks.push_back(mask); - } break; + auto mask = ReadTagBlock(stream, MaskTag); + layer->masks.push_back(mask); + } + break; case TagCode::MarkerList: { - ReadMarkerList(stream, &layer->markers); - } break; + ReadMarkerList(stream, &layer->markers); + } + break; case TagCode::Transform2D: { - layer->transform = new Transform2D(); - auto transform = layer->transform; - ReadTagBlock(stream, transform, Transform2DTag); - auto hasPosition = (transform->position->animatable() || - transform->position->getValueAt(0) != Point::Zero()); - auto hasXPosition = - (transform->xPosition->animatable() || transform->xPosition->getValueAt(0) != 0); - auto hasYPosition = - (transform->yPosition->animatable() || transform->yPosition->getValueAt(0) != 0); - if (hasPosition || (!hasXPosition && !hasYPosition)) { - delete transform->xPosition; - transform->xPosition = nullptr; - delete transform->yPosition; - transform->yPosition = nullptr; - } else { - delete transform->position; - transform->position = nullptr; - } - } break; + layer->transform = new Transform2D(); + auto transform = layer->transform; + ReadTagBlock(stream, transform, Transform2DTag); + auto hasPosition = (transform->position->animatable() || + transform->position->getValueAt(0) != Point::Zero()); + auto hasXPosition = + (transform->xPosition->animatable() || transform->xPosition->getValueAt(0) != 0); + auto hasYPosition = + (transform->yPosition->animatable() || transform->yPosition->getValueAt(0) != 0); + if (hasPosition || (!hasXPosition && !hasYPosition)) { + delete transform->xPosition; + transform->xPosition = nullptr; + delete transform->yPosition; + transform->yPosition = nullptr; + } else { + delete transform->position; + transform->position = nullptr; + } + } + break; case TagCode::CachePolicy: - ReadCachePolicy(stream, layer); - break; + ReadCachePolicy(stream, layer); + break; case TagCode::SolidColor: - Condition(layer->type() == LayerType::Solid, - ReadSolidColor(stream, static_cast(layer))); - break; + Condition(layer->type() == LayerType::Solid, + ReadSolidColor(stream, static_cast(layer))); + break; case TagCode::TextSource: - Condition(layer->type() == LayerType::Text, - ReadTagBlock(stream, static_cast(layer), TextSourceTag)); - break; + Condition(layer->type() == LayerType::Text, + ReadTagBlock(stream, static_cast(layer), TextSourceTag)); + break; case TagCode::TextSourceV2: - Condition(layer->type() == LayerType::Text, - ReadTagBlock(stream, static_cast(layer), TextSourceTagV2)); - break; + Condition(layer->type() == LayerType::Text, + ReadTagBlock(stream, static_cast(layer), TextSourceTagV2)); + break; case TagCode::TextSourceV3: - Condition(layer->type() == LayerType::Text, - ReadTagBlock(stream, static_cast(layer), TextSourceTagV3)); - break; + Condition(layer->type() == LayerType::Text, + ReadTagBlock(stream, static_cast(layer), TextSourceTagV3)); + break; case TagCode::TextPathOption: - if (layer->type() == LayerType::Text) { - auto textLayer = static_cast(layer); - textLayer->pathOption = new TextPathOptions(); - ReadTagBlock(stream, textLayer->pathOption, TextPathOptionTag); - } - break; + if (layer->type() == LayerType::Text) { + auto textLayer = static_cast(layer); + textLayer->pathOption = new TextPathOptions(); + ReadTagBlock(stream, textLayer->pathOption, TextPathOptionTag); + } + break; case TagCode::TextMoreOption: - if (layer->type() == LayerType::Text) { - auto textLayer = static_cast(layer); - textLayer->moreOption = new TextMoreOptions(); - ReadTagBlock(stream, textLayer->moreOption, TextMoreOptionTag); - } - break; + if (layer->type() == LayerType::Text) { + auto textLayer = static_cast(layer); + textLayer->moreOption = new TextMoreOptions(); + ReadTagBlock(stream, textLayer->moreOption, TextMoreOptionTag); + } + break; case TagCode::TextAnimator: - Condition(layer->type() == LayerType::Text, - ReadTextAnimator(stream, static_cast(layer))); - break; + Condition(layer->type() == LayerType::Text, + ReadTextAnimator(stream, static_cast(layer))); + break; case TagCode::CompositionReference: - Condition(layer->type() == LayerType::PreCompose, - ReadCompositionReference(stream, static_cast(layer))); - break; + Condition(layer->type() == LayerType::PreCompose, + ReadCompositionReference(stream, static_cast(layer))); + break; case TagCode::ImageReference: - Condition(layer->type() == LayerType::Image, - ReadImageReference(stream, static_cast(layer))); - break; + Condition(layer->type() == LayerType::Image, + ReadImageReference(stream, static_cast(layer))); + break; case TagCode::ImageFillRule: case TagCode::ImageFillRuleV2: - Condition(layer->type() == LayerType::Image, - ReadImageFillRule(stream, static_cast(layer), code)); - break; - default: - if (ReadEffect(stream, code, layer)) { - break; - } - if (ReadLayerStyles(stream, code, layer)) { + Condition(layer->type() == LayerType::Image, + ReadImageFillRule(stream, static_cast(layer), code)); break; - } - if (layer->type() == LayerType::Shape && - ReadShape(stream, code, &(static_cast(layer)->contents))) { + default: + if (ReadEffect(stream, code, layer)) { + break; + } + if (ReadLayerStyles(stream, code, layer)) { + break; + } + if (layer->type() == LayerType::Shape && + ReadShape(stream, code, &(static_cast(layer)->contents))) { + break; + } break; - } - break; - } + } } Layer* ReadLayer(DecodeStream* stream) { - auto layerType = static_cast(stream->readUint8()); - Layer* layer = nullptr; - switch (layerType) { + auto layerType = static_cast(stream->readUint8()); + Layer* layer = nullptr; + switch (layerType) { case LayerType::Null: - layer = new NullLayer(); - break; + layer = new NullLayer(); + break; case LayerType::Solid: - layer = new SolidLayer(); - break; + layer = new SolidLayer(); + break; case LayerType::Text: - layer = new TextLayer(); - break; + layer = new TextLayer(); + break; case LayerType::Shape: - layer = new ShapeLayer(); - break; + layer = new ShapeLayer(); + break; case LayerType::Image: - layer = new ImageLayer(); - break; + layer = new ImageLayer(); + break; case LayerType::PreCompose: - layer = new PreComposeLayer(); - break; + layer = new PreComposeLayer(); + break; default: - layer = new Layer(); - break; - } - layer->id = stream->readEncodedUint32(); - ReadTags(stream, layer, ReadTagsOfLayer); - return layer; + layer = new Layer(); + break; + } + layer->id = stream->readEncodedUint32(); + ReadTags(stream, layer, ReadTagsOfLayer); + return layer; } #undef Condition TagCode WriteLayer(EncodeStream* stream, Layer* layer) { - stream->writeUint8(static_cast(layer->type())); - stream->writeEncodedUint32(layer->id); + stream->writeUint8(static_cast(layer->type())); + stream->writeEncodedUint32(layer->id); - if (layer->motionBlur) { - WriteTagBlock(stream, layer, LayerAttributesTag); - WriteTagBlock(stream, layer, LayerAttributesExtraTag); - } else if (!layer->name.empty()) { - WriteTagBlock(stream, layer, LayerAttributesTagV2); - } else { - WriteTagBlock(stream, layer, LayerAttributesTag); - } + if (layer->motionBlur) { + WriteTagBlock(stream, layer, LayerAttributesTag); + WriteTagBlock(stream, layer, LayerAttributesExtraTag); + } else if (!layer->name.empty()) { + WriteTagBlock(stream, layer, LayerAttributesTagV2); + } else { + WriteTagBlock(stream, layer, LayerAttributesTag); + } - for (auto& mask : layer->masks) { - WriteTagBlock(stream, mask, MaskTag); - } - if (layer->markers.size() > 0) { - WriteTag(stream, &layer->markers, WriteMarkerList); - } - WriteEffects(stream, layer->effects); - WriteLayerStyles(stream, layer->layerStyles); - if (layer->transform != nullptr) { - WriteTagBlock(stream, layer->transform, Transform2DTag); - } - if (layer->cachePolicy != CachePolicy::Auto) { - WriteTag(stream, layer, WriteCachePolicy); - } - switch (layer->type()) { + for (auto& mask : layer->masks) { + WriteTagBlock(stream, mask, MaskTag); + } + if (layer->markers.size() > 0) { + WriteTag(stream, &layer->markers, WriteMarkerList); + } + WriteEffects(stream, layer->effects); + WriteLayerStyles(stream, layer->layerStyles); + if (layer->transform != nullptr) { + WriteTagBlock(stream, layer->transform, Transform2DTag); + } + if (layer->cachePolicy != CachePolicy::Auto) { + WriteTag(stream, layer, WriteCachePolicy); + } + switch (layer->type()) { case LayerType::Solid: - WriteTag(stream, static_cast(layer), WriteSolidColor); - break; + WriteTag(stream, static_cast(layer), WriteSolidColor); + break; case LayerType::Shape: - WriteShape(stream, &(static_cast(layer)->contents)); - break; + WriteShape(stream, &(static_cast(layer)->contents)); + break; case LayerType::PreCompose: - WriteTag(stream, static_cast(layer), WriteCompositionReference); - break; + WriteTag(stream, static_cast(layer), WriteCompositionReference); + break; case LayerType::Image: { - auto imageLayer = static_cast(layer); - WriteTag(stream, imageLayer, WriteImageReference); - if (imageLayer->imageFillRule != nullptr && - (imageLayer->imageFillRule->scaleMode != PAGScaleMode::LetterBox || - imageLayer->imageFillRule->timeRemap != nullptr)) { - WriteImageFillRule(stream, imageLayer->imageFillRule); - } - } break; + auto imageLayer = static_cast(layer); + WriteTag(stream, imageLayer, WriteImageReference); + if (imageLayer->imageFillRule != nullptr && + (imageLayer->imageFillRule->scaleMode != PAGScaleMode::LetterBox || + imageLayer->imageFillRule->timeRemap != nullptr)) { + WriteImageFillRule(stream, imageLayer->imageFillRule); + } + } + break; case LayerType::Text: { - auto textLayer = static_cast(layer); - auto textDocument = textLayer->getTextDocument(); - if (textDocument != nullptr && textDocument->direction != TextDirection::Default) { - WriteTagBlock(stream, textLayer, TextSourceTagV3); - } else if (textDocument != nullptr && textDocument->backgroundAlpha != 0) { - WriteTagBlock(stream, textLayer, TextSourceTagV2); - } else { - WriteTagBlock(stream, textLayer, TextSourceTag); - } - auto pathOption = textLayer->pathOption; - auto moreOption = textLayer->moreOption; - if (pathOption != nullptr && pathOption->path) { - WriteTagBlock(stream, pathOption, TextPathOptionTag); - } - if (moreOption != nullptr) { - WriteTagBlock(stream, moreOption, TextMoreOptionTag); - } - for (auto& animator : textLayer->animators) { - WriteTag(stream, animator, WriteTextAnimator); - } - } break; + auto textLayer = static_cast(layer); + auto textDocument = textLayer->getTextDocument(); + if (textDocument != nullptr && textDocument->direction != TextDirection::Default) { + WriteTagBlock(stream, textLayer, TextSourceTagV3); + } else if (textDocument != nullptr && textDocument->backgroundAlpha != 0) { + WriteTagBlock(stream, textLayer, TextSourceTagV2); + } else { + WriteTagBlock(stream, textLayer, TextSourceTag); + } + auto pathOption = textLayer->pathOption; + auto moreOption = textLayer->moreOption; + if (pathOption != nullptr && pathOption->path) { + WriteTagBlock(stream, pathOption, TextPathOptionTag); + } + if (moreOption != nullptr) { + WriteTagBlock(stream, moreOption, TextMoreOptionTag); + } + for (auto& animator : textLayer->animators) { + WriteTag(stream, animator, WriteTextAnimator); + } + } + break; default: - break; - } - WriteEndTag(stream); - return TagCode::LayerBlock; + break; + } + WriteEndTag(stream); + return TagCode::LayerBlock; } } // namespace pag diff --git a/src/codec/tags/MarkerTag.cpp b/src/codec/tags/MarkerTag.cpp index 5155f4ce03..1033a095ed 100644 --- a/src/codec/tags/MarkerTag.cpp +++ b/src/codec/tags/MarkerTag.cpp @@ -21,41 +21,41 @@ namespace pag { void ReadMarkerList(DecodeStream* stream, std::vector* markers) { - std::vector flagList; - - auto count = stream->readEncodedUint32(); - for (size_t i = 0; i < count; i++) { - auto hasDuration = stream->readBitBoolean(); - flagList.push_back(hasDuration); - } - - for (auto hasDuration : flagList) { - auto marker = new Marker(); - marker->startTime = ReadTime(stream); - if (hasDuration) { - marker->duration = ReadTime(stream); + std::vector flagList; + + auto count = stream->readEncodedUint32(); + for (size_t i = 0; i < count; i++) { + auto hasDuration = stream->readBitBoolean(); + flagList.push_back(hasDuration); + } + + for (auto hasDuration : flagList) { + auto marker = new Marker(); + marker->startTime = ReadTime(stream); + if (hasDuration) { + marker->duration = ReadTime(stream); + } + marker->comment = stream->readUTF8String(); + markers->push_back(marker); } - marker->comment = stream->readUTF8String(); - markers->push_back(marker); - } } TagCode WriteMarkerList(EncodeStream* stream, std::vector* markers) { - stream->writeEncodedUint32(static_cast(markers->size())); - for (auto marker : *markers) { - bool hasDuration = (marker->duration != 0); - stream->writeBitBoolean(hasDuration); - } - - for (auto marker : *markers) { - bool hasDuration = (marker->duration != 0); - - WriteTime(stream, marker->startTime); - if (hasDuration) { - WriteTime(stream, marker->duration); + stream->writeEncodedUint32(static_cast(markers->size())); + for (auto marker : *markers) { + bool hasDuration = (marker->duration != 0); + stream->writeBitBoolean(hasDuration); + } + + for (auto marker : *markers) { + bool hasDuration = (marker->duration != 0); + + WriteTime(stream, marker->startTime); + if (hasDuration) { + WriteTime(stream, marker->duration); + } + stream->writeUTF8String(marker->comment); } - stream->writeUTF8String(marker->comment); - } - return TagCode::MarkerList; + return TagCode::MarkerList; } } // namespace pag diff --git a/src/codec/tags/MaskTag.cpp b/src/codec/tags/MaskTag.cpp index 7c13e923d1..bc3f85087c 100644 --- a/src/codec/tags/MaskTag.cpp +++ b/src/codec/tags/MaskTag.cpp @@ -20,14 +20,14 @@ namespace pag { std::unique_ptr MaskTag(MaskData* mask) { - auto tagConfig = new BlockConfig(TagCode::MaskBlock); - AddAttribute(tagConfig, &mask->id, AttributeType::FixedValue, ZeroID); - AddAttribute(tagConfig, &mask->inverted, AttributeType::BitFlag, false); - AddAttribute(tagConfig, &mask->maskMode, AttributeType::Value, MaskMode::Add); - AddAttribute(tagConfig, &mask->maskPath, AttributeType::SimpleProperty, - PathHandle(new PathData())); - AddAttribute(tagConfig, &mask->maskOpacity, AttributeType::SimpleProperty, Opaque); - AddAttribute(tagConfig, &mask->maskExpansion, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::MaskBlock); + AddAttribute(tagConfig, &mask->id, AttributeType::FixedValue, ZeroID); + AddAttribute(tagConfig, &mask->inverted, AttributeType::BitFlag, false); + AddAttribute(tagConfig, &mask->maskMode, AttributeType::Value, MaskMode::Add); + AddAttribute(tagConfig, &mask->maskPath, AttributeType::SimpleProperty, + PathHandle(new PathData())); + AddAttribute(tagConfig, &mask->maskOpacity, AttributeType::SimpleProperty, Opaque); + AddAttribute(tagConfig, &mask->maskExpansion, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/PerformanceTag.cpp b/src/codec/tags/PerformanceTag.cpp index 7a0df4f90d..14863570e5 100644 --- a/src/codec/tags/PerformanceTag.cpp +++ b/src/codec/tags/PerformanceTag.cpp @@ -20,17 +20,17 @@ namespace pag { void ReadPerformanceTag(DecodeStream* stream, PerformanceData* data) { - data->renderingTime = stream->readEncodedInt64(); - data->imageDecodingTime = stream->readEncodedInt64(); - data->presentingTime = stream->readEncodedInt64(); - data->graphicsMemory = stream->readEncodedInt64(); + data->renderingTime = stream->readEncodedInt64(); + data->imageDecodingTime = stream->readEncodedInt64(); + data->presentingTime = stream->readEncodedInt64(); + data->graphicsMemory = stream->readEncodedInt64(); } TagCode WritePerformanceTag(EncodeStream* stream, PerformanceData* data) { - stream->writeEncodedInt64(data->renderingTime); - stream->writeEncodedInt64(data->imageDecodingTime); - stream->writeEncodedInt64(data->presentingTime); - stream->writeEncodedInt64(data->graphicsMemory); - return TagCode::Performance; + stream->writeEncodedInt64(data->renderingTime); + stream->writeEncodedInt64(data->imageDecodingTime); + stream->writeEncodedInt64(data->presentingTime); + stream->writeEncodedInt64(data->graphicsMemory); + return TagCode::Performance; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/ShapeTag.cpp b/src/codec/tags/ShapeTag.cpp index 0fe516deba..19f5b9d825 100644 --- a/src/codec/tags/ShapeTag.cpp +++ b/src/codec/tags/ShapeTag.cpp @@ -37,37 +37,39 @@ using ReadShapeHandler = ShapeElement*(DecodeStream* stream); template static std::function MakeReadShapeHandler( std::unique_ptr (*ConfigMaker)(T*)) { - return [ConfigMaker](DecodeStream* stream) { return ReadTagBlock(stream, ConfigMaker); }; + return [ConfigMaker](DecodeStream* stream) { + return ReadTagBlock(stream, ConfigMaker); + }; } static const std::unordered_map, EnumClassHash> - readShapeHandlers = { - {TagCode::ShapeGroup, MakeReadShapeHandler(ShapeGroupTag)}, - {TagCode::Rectangle, MakeReadShapeHandler(RectangleTag)}, - {TagCode::Ellipse, MakeReadShapeHandler(EllipseTag)}, - {TagCode::PolyStar, MakeReadShapeHandler(PolyStarTag)}, - {TagCode::ShapePath, MakeReadShapeHandler(ShapePathTag)}, - {TagCode::Fill, MakeReadShapeHandler(FillTag)}, - {TagCode::Stroke, MakeReadShapeHandler(StrokeTag)}, - {TagCode::GradientFill, MakeReadShapeHandler(GradientFillTag)}, - {TagCode::GradientStroke, MakeReadShapeHandler(GradientStrokeTag)}, - {TagCode::MergePaths, MakeReadShapeHandler(MergePathsTag)}, - {TagCode::TrimPaths, MakeReadShapeHandler(TrimPathsTag)}, - {TagCode::Repeater, MakeReadShapeHandler(RepeaterTag)}, - {TagCode::RoundCorners, MakeReadShapeHandler(RoundCornersTag)}, +readShapeHandlers = { + {TagCode::ShapeGroup, MakeReadShapeHandler(ShapeGroupTag)}, + {TagCode::Rectangle, MakeReadShapeHandler(RectangleTag)}, + {TagCode::Ellipse, MakeReadShapeHandler(EllipseTag)}, + {TagCode::PolyStar, MakeReadShapeHandler(PolyStarTag)}, + {TagCode::ShapePath, MakeReadShapeHandler(ShapePathTag)}, + {TagCode::Fill, MakeReadShapeHandler(FillTag)}, + {TagCode::Stroke, MakeReadShapeHandler(StrokeTag)}, + {TagCode::GradientFill, MakeReadShapeHandler(GradientFillTag)}, + {TagCode::GradientStroke, MakeReadShapeHandler(GradientStrokeTag)}, + {TagCode::MergePaths, MakeReadShapeHandler(MergePathsTag)}, + {TagCode::TrimPaths, MakeReadShapeHandler(TrimPathsTag)}, + {TagCode::Repeater, MakeReadShapeHandler(RepeaterTag)}, + {TagCode::RoundCorners, MakeReadShapeHandler(RoundCornersTag)}, }; bool ReadShape(DecodeStream* stream, TagCode code, std::vector* contents) { - auto iter = readShapeHandlers.find(code); - if (iter == readShapeHandlers.end()) { - return false; - } - auto shape = iter->second(stream); - if (shape == nullptr) { - return false; - } - contents->push_back(shape); - return true; + auto iter = readShapeHandlers.find(code); + if (iter == readShapeHandlers.end()) { + return false; + } + auto shape = iter->second(stream); + if (shape == nullptr) { + return false; + } + contents->push_back(shape); + return true; } using WriteShapeHandler = void(EncodeStream* stream, ShapeElement* shape); @@ -75,36 +77,37 @@ using WriteShapeHandler = void(EncodeStream* stream, ShapeElement* shape); template static std::function MakeWriteShapeHandler( std::unique_ptr (*ConfigMaker)(T*)) { - return [ConfigMaker](EncodeStream* stream, ShapeElement* shape) { - WriteTagBlock(stream, static_cast(shape), ConfigMaker); - }; + return [ConfigMaker](EncodeStream* stream, ShapeElement* shape) { + WriteTagBlock(stream, static_cast(shape), ConfigMaker); + }; } static const std::unordered_map, EnumClassHash> - writeShapeHandlers = { - {ShapeType::ShapeGroup, MakeWriteShapeHandler(ShapeGroupTag)}, - {ShapeType::Rectangle, MakeWriteShapeHandler(RectangleTag)}, - {ShapeType::Ellipse, MakeWriteShapeHandler(EllipseTag)}, - {ShapeType::PolyStar, MakeWriteShapeHandler(PolyStarTag)}, - {ShapeType::ShapePath, MakeWriteShapeHandler(ShapePathTag)}, - {ShapeType::Fill, MakeWriteShapeHandler(FillTag)}, - {ShapeType::Stroke, MakeWriteShapeHandler(StrokeTag)}, - {ShapeType::GradientFill, MakeWriteShapeHandler(GradientFillTag)}, - {ShapeType::GradientStroke, - MakeWriteShapeHandler(GradientStrokeTag)}, - {ShapeType::MergePaths, MakeWriteShapeHandler(MergePathsTag)}, - {ShapeType::TrimPaths, MakeWriteShapeHandler(TrimPathsTag)}, - {ShapeType::Repeater, MakeWriteShapeHandler(RepeaterTag)}, - {ShapeType::RoundCorners, MakeWriteShapeHandler(RoundCornersTag)}, +writeShapeHandlers = { + {ShapeType::ShapeGroup, MakeWriteShapeHandler(ShapeGroupTag)}, + {ShapeType::Rectangle, MakeWriteShapeHandler(RectangleTag)}, + {ShapeType::Ellipse, MakeWriteShapeHandler(EllipseTag)}, + {ShapeType::PolyStar, MakeWriteShapeHandler(PolyStarTag)}, + {ShapeType::ShapePath, MakeWriteShapeHandler(ShapePathTag)}, + {ShapeType::Fill, MakeWriteShapeHandler(FillTag)}, + {ShapeType::Stroke, MakeWriteShapeHandler(StrokeTag)}, + {ShapeType::GradientFill, MakeWriteShapeHandler(GradientFillTag)}, + { ShapeType::GradientStroke, + MakeWriteShapeHandler(GradientStrokeTag) + }, + {ShapeType::MergePaths, MakeWriteShapeHandler(MergePathsTag)}, + {ShapeType::TrimPaths, MakeWriteShapeHandler(TrimPathsTag)}, + {ShapeType::Repeater, MakeWriteShapeHandler(RepeaterTag)}, + {ShapeType::RoundCorners, MakeWriteShapeHandler(RoundCornersTag)}, }; void WriteShape(EncodeStream* stream, const std::vector* contents) { - auto handleShape = [stream](ShapeElement* shape) { - auto iter = writeShapeHandlers.find(shape->type()); - if (iter != writeShapeHandlers.end()) { - iter->second(stream, shape); - } - }; - std::for_each(contents->begin(), contents->end(), handleShape); + auto handleShape = [stream](ShapeElement* shape) { + auto iter = writeShapeHandlers.find(shape->type()); + if (iter != writeShapeHandlers.end()) { + iter->second(stream, shape); + } + }; + std::for_each(contents->begin(), contents->end(), handleShape); } } // namespace pag diff --git a/src/codec/tags/SolidColor.cpp b/src/codec/tags/SolidColor.cpp index 16c4742c84..5f875d895d 100644 --- a/src/codec/tags/SolidColor.cpp +++ b/src/codec/tags/SolidColor.cpp @@ -21,15 +21,15 @@ namespace pag { void ReadSolidColor(DecodeStream* stream, SolidLayer* layer) { - layer->solidColor = ReadColor(stream); - layer->width = stream->readEncodedInt32(); - layer->height = stream->readEncodedInt32(); + layer->solidColor = ReadColor(stream); + layer->width = stream->readEncodedInt32(); + layer->height = stream->readEncodedInt32(); } TagCode WriteSolidColor(EncodeStream* stream, SolidLayer* layer) { - WriteColor(stream, layer->solidColor); - stream->writeEncodedInt32(layer->width); - stream->writeEncodedInt32(layer->height); - return TagCode::SolidColor; + WriteColor(stream, layer->solidColor); + stream->writeEncodedInt32(layer->width); + stream->writeEncodedInt32(layer->height); + return TagCode::SolidColor; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/TimeStretchMode.cpp b/src/codec/tags/TimeStretchMode.cpp index fb1a168720..d83c20db80 100644 --- a/src/codec/tags/TimeStretchMode.cpp +++ b/src/codec/tags/TimeStretchMode.cpp @@ -20,25 +20,25 @@ namespace pag { void ReadTimeStretchMode(DecodeStream* stream, CodecContext* context) { - context->timeStretchMode = ReadEnum(stream); - auto hasTimeRange = stream->readBoolean(); - if (hasTimeRange) { - if (context->scaledTimeRange == nullptr) { - context->scaledTimeRange = new TimeRange(); + context->timeStretchMode = ReadEnum(stream); + auto hasTimeRange = stream->readBoolean(); + if (hasTimeRange) { + if (context->scaledTimeRange == nullptr) { + context->scaledTimeRange = new TimeRange(); + } + context->scaledTimeRange->start = ReadTime(stream); + context->scaledTimeRange->end = ReadTime(stream); } - context->scaledTimeRange->start = ReadTime(stream); - context->scaledTimeRange->end = ReadTime(stream); - } } TagCode WriteTimeStretchMode(EncodeStream* stream, const File* file) { - WriteEnum(stream, file->timeStretchMode); - auto timeRange = file->scaledTimeRange; - stream->writeBoolean(file->hasScaledTimeRange()); - if (file->hasScaledTimeRange()) { - WriteTime(stream, timeRange.start); - WriteTime(stream, timeRange.end); - } - return TagCode::TimeStretchMode; + WriteEnum(stream, file->timeStretchMode); + auto timeRange = file->scaledTimeRange; + stream->writeBoolean(file->hasScaledTimeRange()); + if (file->hasScaledTimeRange()) { + WriteTime(stream, timeRange.start); + WriteTime(stream, timeRange.end); + } + return TagCode::TimeStretchMode; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/Transform2D.cpp b/src/codec/tags/Transform2D.cpp index 6bde65d8c5..4cb4fb8400 100644 --- a/src/codec/tags/Transform2D.cpp +++ b/src/codec/tags/Transform2D.cpp @@ -21,15 +21,15 @@ namespace pag { std::unique_ptr Transform2DTag(Transform2D* transform) { - auto tagConfig = new BlockConfig(TagCode::Transform2D); - AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &transform->xPosition, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->yPosition, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, - Point::Make(1, 1)); - AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->opacity, AttributeType::SimpleProperty, Opaque); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::Transform2D); + AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &transform->xPosition, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->yPosition, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, + Point::Make(1, 1)); + AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->opacity, AttributeType::SimpleProperty, Opaque); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/VectorCompositionTag.cpp b/src/codec/tags/VectorCompositionTag.cpp index fd0c7395ba..77140ce764 100644 --- a/src/codec/tags/VectorCompositionTag.cpp +++ b/src/codec/tags/VectorCompositionTag.cpp @@ -25,32 +25,33 @@ namespace pag { void ReadTagsOfVectorComposition(DecodeStream* stream, TagCode code, VectorComposition* composition) { - switch (code) { + switch (code) { case TagCode::LayerBlock: { - auto layer = ReadLayer(stream); - composition->layers.push_back(layer); - } break; + auto layer = ReadLayer(stream); + composition->layers.push_back(layer); + } + break; default: - ReadTagsOfComposition(stream, code, composition); - break; - } + ReadTagsOfComposition(stream, code, composition); + break; + } } VectorComposition* ReadVectorComposition(DecodeStream* stream) { - auto composition = new VectorComposition(); - composition->id = stream->readEncodedUint32(); - ReadTags(stream, composition, ReadTagsOfVectorComposition); - Codec::InstallReferences(composition->layers); - return composition; + auto composition = new VectorComposition(); + composition->id = stream->readEncodedUint32(); + ReadTags(stream, composition, ReadTagsOfVectorComposition); + Codec::InstallReferences(composition->layers); + return composition; } TagCode WriteVectorComposition(EncodeStream* stream, VectorComposition* composition) { - stream->writeEncodedUint32(composition->id); - WriteTagsOfComposition(stream, composition); - for (auto& layer : composition->layers) { - WriteTag(stream, layer, WriteLayer); - } - WriteEndTag(stream); - return TagCode::VectorCompositionBlock; + stream->writeEncodedUint32(composition->id); + WriteTagsOfComposition(stream, composition); + for (auto& layer : composition->layers) { + WriteTag(stream, layer, WriteLayer); + } + WriteEndTag(stream); + return TagCode::VectorCompositionBlock; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/VideoCompositionTag.cpp b/src/codec/tags/VideoCompositionTag.cpp index 8d3573e1f0..ac03607763 100644 --- a/src/codec/tags/VideoCompositionTag.cpp +++ b/src/codec/tags/VideoCompositionTag.cpp @@ -26,46 +26,47 @@ namespace pag { void ReadTagsOfVideoComposition(DecodeStream* stream, TagCode code, std::pair* parameter) { - auto composition = parameter->first; - auto hasAlpha = parameter->second; - switch (code) { + auto composition = parameter->first; + auto hasAlpha = parameter->second; + switch (code) { case TagCode::VideoSequence: { - auto sequence = ReadVideoSequence(stream, hasAlpha); - sequence->composition = composition; - composition->sequences.push_back(sequence); - } break; + auto sequence = ReadVideoSequence(stream, hasAlpha); + sequence->composition = composition; + composition->sequences.push_back(sequence); + } + break; default: - ReadTagsOfComposition(stream, code, composition); - break; - } + ReadTagsOfComposition(stream, code, composition); + break; + } } VideoComposition* ReadVideoComposition(DecodeStream* stream) { - auto composition = new VideoComposition(); - composition->id = stream->readEncodedUint32(); - auto hasAlpha = stream->readBoolean(); - auto parameter = std::make_pair(composition, hasAlpha); - ReadTags(stream, ¶meter, ReadTagsOfVideoComposition); - return composition; + auto composition = new VideoComposition(); + composition->id = stream->readEncodedUint32(); + auto hasAlpha = stream->readBoolean(); + auto parameter = std::make_pair(composition, hasAlpha); + ReadTags(stream, ¶meter, ReadTagsOfVideoComposition); + return composition; } static bool lessFirst(const VideoSequence* item1, const VideoSequence* item2) { - return item1->width < item2->width; + return item1->width < item2->width; } TagCode WriteVideoComposition(EncodeStream* stream, VideoComposition* composition) { - auto sequences = composition->sequences; - std::sort(sequences.begin(), sequences.end(), lessFirst); - auto hasAlpha = - !sequences.empty() && (sequences[0]->alphaStartY > 0 || sequences[0]->alphaStartX > 0); - stream->writeEncodedUint32(composition->id); - stream->writeBoolean(hasAlpha); - WriteTagsOfComposition(stream, composition); - for (auto sequence : sequences) { - auto parameter = std::make_pair(sequence, hasAlpha); - WriteTag(stream, ¶meter, WriteVideoSequence); - } - WriteEndTag(stream); - return TagCode::VideoCompositionBlock; + auto sequences = composition->sequences; + std::sort(sequences.begin(), sequences.end(), lessFirst); + auto hasAlpha = + !sequences.empty() && (sequences[0]->alphaStartY > 0 || sequences[0]->alphaStartX > 0); + stream->writeEncodedUint32(composition->id); + stream->writeBoolean(hasAlpha); + WriteTagsOfComposition(stream, composition); + for (auto sequence : sequences) { + auto parameter = std::make_pair(sequence, hasAlpha); + WriteTag(stream, ¶meter, WriteVideoSequence); + } + WriteEndTag(stream); + return TagCode::VideoCompositionBlock; } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/VideoSequence.cpp b/src/codec/tags/VideoSequence.cpp index 29885789c0..207c7bcaf3 100644 --- a/src/codec/tags/VideoSequence.cpp +++ b/src/codec/tags/VideoSequence.cpp @@ -21,90 +21,90 @@ namespace pag { VideoSequence* ReadVideoSequence(DecodeStream* stream, bool hasAlpha) { - auto sequence = new VideoSequence(); - sequence->width = stream->readEncodedInt32(); - sequence->height = stream->readEncodedInt32(); - sequence->frameRate = stream->readFloat(); + auto sequence = new VideoSequence(); + sequence->width = stream->readEncodedInt32(); + sequence->height = stream->readEncodedInt32(); + sequence->frameRate = stream->readFloat(); - if (hasAlpha) { - sequence->alphaStartX = stream->readEncodedInt32(); - sequence->alphaStartY = stream->readEncodedInt32(); - } - - auto sps = ReadByteDataWithStartCode(stream); - auto pps = ReadByteDataWithStartCode(stream); - sequence->headers.push_back(sps.release()); - sequence->headers.push_back(pps.release()); + if (hasAlpha) { + sequence->alphaStartX = stream->readEncodedInt32(); + sequence->alphaStartY = stream->readEncodedInt32(); + } - auto count = stream->readEncodedUint32(); - for (uint32_t i = 0; i < count; i++) { - auto videoFrame = new VideoFrame(); - sequence->frames.push_back(videoFrame); - videoFrame->isKeyframe = stream->readBitBoolean(); - } - for (uint32_t i = 0; i < count; i++) { - auto videoFrame = sequence->frames[i]; - videoFrame->frame = ReadTime(stream); - videoFrame->fileBytes = ReadByteDataWithStartCode(stream).release(); - } + auto sps = ReadByteDataWithStartCode(stream); + auto pps = ReadByteDataWithStartCode(stream); + sequence->headers.push_back(sps.release()); + sequence->headers.push_back(pps.release()); - if (stream->bytesAvailable() > 0) { - count = stream->readEncodedUint32(); + auto count = stream->readEncodedUint32(); + for (uint32_t i = 0; i < count; i++) { + auto videoFrame = new VideoFrame(); + sequence->frames.push_back(videoFrame); + videoFrame->isKeyframe = stream->readBitBoolean(); + } for (uint32_t i = 0; i < count; i++) { - TimeRange staticTimeRange = {}; - staticTimeRange.start = ReadTime(stream); - staticTimeRange.end = ReadTime(stream); - sequence->staticTimeRanges.push_back(staticTimeRange); + auto videoFrame = sequence->frames[i]; + videoFrame->frame = ReadTime(stream); + videoFrame->fileBytes = ReadByteDataWithStartCode(stream).release(); } - } - return sequence; + if (stream->bytesAvailable() > 0) { + count = stream->readEncodedUint32(); + for (uint32_t i = 0; i < count; i++) { + TimeRange staticTimeRange = {}; + staticTimeRange.start = ReadTime(stream); + staticTimeRange.end = ReadTime(stream); + sequence->staticTimeRanges.push_back(staticTimeRange); + } + } + + return sequence; } static void WriteByteDataWithoutStartCode(EncodeStream* stream, ByteData* byteData) { - auto length = static_cast(byteData->length()); - if (length < 4) { - length = 0; - } else { - length -= 4; - } - stream->writeEncodedUint32(length); - // Skip Annex B Prefix - stream->writeBytes(byteData->data() + 4, length); + auto length = static_cast(byteData->length()); + if (length < 4) { + length = 0; + } else { + length -= 4; + } + stream->writeEncodedUint32(length); + // Skip Annex B Prefix + stream->writeBytes(byteData->data() + 4, length); } TagCode WriteVideoSequence(EncodeStream* stream, std::pair* parameter) { - auto sequence = parameter->first; - auto hasAlpha = parameter->second; - stream->writeEncodedInt32(sequence->width); - stream->writeEncodedInt32(sequence->height); - stream->writeFloat(sequence->frameRate); + auto sequence = parameter->first; + auto hasAlpha = parameter->second; + stream->writeEncodedInt32(sequence->width); + stream->writeEncodedInt32(sequence->height); + stream->writeFloat(sequence->frameRate); - if (hasAlpha) { - stream->writeEncodedInt32(sequence->alphaStartX); - stream->writeEncodedInt32(sequence->alphaStartY); - } + if (hasAlpha) { + stream->writeEncodedInt32(sequence->alphaStartX); + stream->writeEncodedInt32(sequence->alphaStartY); + } - WriteByteDataWithoutStartCode(stream, sequence->headers[0]); // sps - WriteByteDataWithoutStartCode(stream, sequence->headers[1]); // pps + WriteByteDataWithoutStartCode(stream, sequence->headers[0]); // sps + WriteByteDataWithoutStartCode(stream, sequence->headers[1]); // pps - auto count = static_cast(sequence->frames.size()); - stream->writeEncodedUint32(count); - for (uint32_t i = 0; i < count; i++) { - stream->writeBitBoolean(sequence->frames[i]->isKeyframe); - } - for (uint32_t i = 0; i < count; i++) { - auto videoFrame = sequence->frames[i]; - WriteTime(stream, videoFrame->frame); - WriteByteDataWithoutStartCode(stream, videoFrame->fileBytes); - } + auto count = static_cast(sequence->frames.size()); + stream->writeEncodedUint32(count); + for (uint32_t i = 0; i < count; i++) { + stream->writeBitBoolean(sequence->frames[i]->isKeyframe); + } + for (uint32_t i = 0; i < count; i++) { + auto videoFrame = sequence->frames[i]; + WriteTime(stream, videoFrame->frame); + WriteByteDataWithoutStartCode(stream, videoFrame->fileBytes); + } - stream->writeEncodedUint32(static_cast(sequence->staticTimeRanges.size())); - for (auto staticTimeRange : sequence->staticTimeRanges) { - WriteTime(stream, staticTimeRange.start); - WriteTime(stream, staticTimeRange.end); - } + stream->writeEncodedUint32(static_cast(sequence->staticTimeRanges.size())); + for (auto staticTimeRange : sequence->staticTimeRanges) { + WriteTime(stream, staticTimeRange.start); + WriteTime(stream, staticTimeRange.end); + } - return TagCode::VideoSequence; + return TagCode::VideoSequence; } } // namespace pag diff --git a/src/codec/tags/effects/BulgeEffect.cpp b/src/codec/tags/effects/BulgeEffect.cpp index 2148854e9e..ce2ca59a48 100644 --- a/src/codec/tags/effects/BulgeEffect.cpp +++ b/src/codec/tags/effects/BulgeEffect.cpp @@ -21,15 +21,15 @@ namespace pag { std::unique_ptr BulgeEffectTag(BulgeEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::BulgeEffect); - AddAttribute(tagConfig, &effect->horizontalRadius, AttributeType::SimpleProperty, 50.0f); - AddAttribute(tagConfig, &effect->verticalRadius, AttributeType::SimpleProperty, 50.0f); - AddAttribute(tagConfig, &effect->bulgeCenter, AttributeType::SpatialProperty, - Point::Make(640.0f, 360.0f)); - AddAttribute(tagConfig, &effect->bulgeHeight, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &effect->taperRadius, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->pinning, AttributeType::DiscreteProperty, false); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::BulgeEffect); + AddAttribute(tagConfig, &effect->horizontalRadius, AttributeType::SimpleProperty, 50.0f); + AddAttribute(tagConfig, &effect->verticalRadius, AttributeType::SimpleProperty, 50.0f); + AddAttribute(tagConfig, &effect->bulgeCenter, AttributeType::SpatialProperty, + Point::Make(640.0f, 360.0f)); + AddAttribute(tagConfig, &effect->bulgeHeight, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &effect->taperRadius, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->pinning, AttributeType::DiscreteProperty, false); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/effects/CornerPinEffect.cpp b/src/codec/tags/effects/CornerPinEffect.cpp index 87facc529c..a9caf6be38 100644 --- a/src/codec/tags/effects/CornerPinEffect.cpp +++ b/src/codec/tags/effects/CornerPinEffect.cpp @@ -21,15 +21,15 @@ namespace pag { std::unique_ptr CornerPinEffectTag(CornerPinEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::CornerPinEffect); - AddAttribute(tagConfig, &effect->upperLeft, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &effect->upperRight, AttributeType::SpatialProperty, - Point::Make(1280.0f, 0.0f)); - AddAttribute(tagConfig, &effect->lowerLeft, AttributeType::SpatialProperty, - Point::Make(0.0f, 720.0f)); - AddAttribute(tagConfig, &effect->lowerRight, AttributeType::SpatialProperty, - Point::Make(1280.0f, 720.0f)); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::CornerPinEffect); + AddAttribute(tagConfig, &effect->upperLeft, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &effect->upperRight, AttributeType::SpatialProperty, + Point::Make(1280.0f, 0.0f)); + AddAttribute(tagConfig, &effect->lowerLeft, AttributeType::SpatialProperty, + Point::Make(0.0f, 720.0f)); + AddAttribute(tagConfig, &effect->lowerRight, AttributeType::SpatialProperty, + Point::Make(1280.0f, 720.0f)); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/effects/DisplacementMapEffect.cpp b/src/codec/tags/effects/DisplacementMapEffect.cpp index 04378aa3df..52c22e7b2c 100644 --- a/src/codec/tags/effects/DisplacementMapEffect.cpp +++ b/src/codec/tags/effects/DisplacementMapEffect.cpp @@ -21,20 +21,20 @@ namespace pag { std::unique_ptr DisplacementMapEffectTag(DisplacementMapEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::DisplacementMapEffect); - AddAttribute(tagConfig, &effect->displacementMapLayer, AttributeType::Value, - static_cast(nullptr)); - AddAttribute(tagConfig, &effect->useForHorizontalDisplacement, AttributeType::DiscreteProperty, - DisplacementMapSource::Red); - AddAttribute(tagConfig, &effect->maxHorizontalDisplacement, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &effect->useForVerticalDisplacement, AttributeType::DiscreteProperty, - DisplacementMapSource::Green); - AddAttribute(tagConfig, &effect->maxVerticalDisplacement, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &effect->displacementMapBehavior, AttributeType::DiscreteProperty, - DisplacementMapBehavior::CenterMap); - AddAttribute(tagConfig, &effect->edgeBehavior, AttributeType::DiscreteProperty, false); - AddAttribute(tagConfig, &effect->expandOutput, AttributeType::DiscreteProperty, true); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::DisplacementMapEffect); + AddAttribute(tagConfig, &effect->displacementMapLayer, AttributeType::Value, + static_cast(nullptr)); + AddAttribute(tagConfig, &effect->useForHorizontalDisplacement, AttributeType::DiscreteProperty, + DisplacementMapSource::Red); + AddAttribute(tagConfig, &effect->maxHorizontalDisplacement, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &effect->useForVerticalDisplacement, AttributeType::DiscreteProperty, + DisplacementMapSource::Green); + AddAttribute(tagConfig, &effect->maxVerticalDisplacement, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &effect->displacementMapBehavior, AttributeType::DiscreteProperty, + DisplacementMapBehavior::CenterMap); + AddAttribute(tagConfig, &effect->edgeBehavior, AttributeType::DiscreteProperty, false); + AddAttribute(tagConfig, &effect->expandOutput, AttributeType::DiscreteProperty, true); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/effects/EffectCompositingOption.cpp b/src/codec/tags/effects/EffectCompositingOption.cpp index e8da4d042e..04cd442acb 100644 --- a/src/codec/tags/effects/EffectCompositingOption.cpp +++ b/src/codec/tags/effects/EffectCompositingOption.cpp @@ -20,29 +20,29 @@ namespace pag { void ReadEffectCompositingMasks(DecodeStream* stream, void* target) { - auto effect = reinterpret_cast(target); - auto length = stream->readEncodedUint32(); - for (uint32_t i = 0; i < length; i++) { - auto mask = ReadMaskID(stream); - effect->maskReferences.push_back(mask); - } + auto effect = reinterpret_cast(target); + auto length = stream->readEncodedUint32(); + for (uint32_t i = 0; i < length; i++) { + auto mask = ReadMaskID(stream); + effect->maskReferences.push_back(mask); + } } bool WriteEffectCompositingMasks(EncodeStream* stream, void* target) { - auto effect = reinterpret_cast(target); - auto length = static_cast(effect->maskReferences.size()); - if (length > 0) { - stream->writeEncodedUint32(length); - for (uint32_t i = 0; i < length; i++) { - auto mask = effect->maskReferences[i]; - WriteMaskID(stream, mask); + auto effect = reinterpret_cast(target); + auto length = static_cast(effect->maskReferences.size()); + if (length > 0) { + stream->writeEncodedUint32(length); + for (uint32_t i = 0; i < length; i++) { + auto mask = effect->maskReferences[i]; + WriteMaskID(stream, mask); + } } - } - return length > 0; + return length > 0; } void EffectCompositingOptionTag(BlockConfig* tagConfig, Effect* effect) { - AddAttribute(tagConfig, &effect->effectOpacity, AttributeType::SimpleProperty, Opaque); - AddCustomAttribute(tagConfig, effect, ReadEffectCompositingMasks, WriteEffectCompositingMasks); + AddAttribute(tagConfig, &effect->effectOpacity, AttributeType::SimpleProperty, Opaque); + AddCustomAttribute(tagConfig, effect, ReadEffectCompositingMasks, WriteEffectCompositingMasks); } } // namespace pag diff --git a/src/codec/tags/effects/FastBlurEffect.cpp b/src/codec/tags/effects/FastBlurEffect.cpp index 99ef4fcb3d..05f3cbbdb1 100644 --- a/src/codec/tags/effects/FastBlurEffect.cpp +++ b/src/codec/tags/effects/FastBlurEffect.cpp @@ -21,12 +21,12 @@ namespace pag { std::unique_ptr FastBlurEffectTag(FastBlurEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::FastBlurEffect); - AddAttribute(tagConfig, &effect->blurriness, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->blurDimensions, AttributeType::DiscreteProperty, - BlurDimensionsDirection::All); - AddAttribute(tagConfig, &effect->repeatEdgePixels, AttributeType::DiscreteProperty, false); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::FastBlurEffect); + AddAttribute(tagConfig, &effect->blurriness, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->blurDimensions, AttributeType::DiscreteProperty, + BlurDimensionsDirection::All); + AddAttribute(tagConfig, &effect->repeatEdgePixels, AttributeType::DiscreteProperty, false); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/effects/GlowEffect.cpp b/src/codec/tags/effects/GlowEffect.cpp index 467bdd5bb1..6f8ad60502 100644 --- a/src/codec/tags/effects/GlowEffect.cpp +++ b/src/codec/tags/effects/GlowEffect.cpp @@ -21,12 +21,12 @@ namespace pag { std::unique_ptr GlowEffectTag(GlowEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::GlowEffect); - AddAttribute(tagConfig, &effect->glowThreshold, AttributeType::SimpleProperty, - static_cast(1.0f)); - AddAttribute(tagConfig, &effect->glowRadius, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &effect->glowIntensity, AttributeType::SimpleProperty, 0.0f); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::GlowEffect); + AddAttribute(tagConfig, &effect->glowThreshold, AttributeType::SimpleProperty, + static_cast(1.0f)); + AddAttribute(tagConfig, &effect->glowRadius, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &effect->glowIntensity, AttributeType::SimpleProperty, 0.0f); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/effects/LevelsIndividualEffect.cpp b/src/codec/tags/effects/LevelsIndividualEffect.cpp index 10c7306690..f80065460a 100644 --- a/src/codec/tags/effects/LevelsIndividualEffect.cpp +++ b/src/codec/tags/effects/LevelsIndividualEffect.cpp @@ -21,32 +21,32 @@ namespace pag { std::unique_ptr LevelsIndividualEffectTag(LevelsIndividualEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::LevelsIndividualEffect); - // RGB - AddAttribute(tagConfig, &effect->inputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->inputWhite, AttributeType::SimpleProperty, 255.0f); - AddAttribute(tagConfig, &effect->gamma, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &effect->outputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->outputWhite, AttributeType::SimpleProperty, 255.0f); - // Red - AddAttribute(tagConfig, &effect->redInputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->redInputWhite, AttributeType::SimpleProperty, 255.0f); - AddAttribute(tagConfig, &effect->redGamma, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &effect->redOutputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->redOutputWhite, AttributeType::SimpleProperty, 255.0f); - // Green - AddAttribute(tagConfig, &effect->greenInputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->greenInputWhite, AttributeType::SimpleProperty, 255.0f); - AddAttribute(tagConfig, &effect->greenGamma, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &effect->greenOutputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->greenOutputWhite, AttributeType::SimpleProperty, 255.0f); - // Blue - AddAttribute(tagConfig, &effect->blueInputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->blueInputWhite, AttributeType::SimpleProperty, 255.0f); - AddAttribute(tagConfig, &effect->blueGamma, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &effect->blueOutputBlack, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->blueOutputWhite, AttributeType::SimpleProperty, 255.0f); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::LevelsIndividualEffect); + // RGB + AddAttribute(tagConfig, &effect->inputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->inputWhite, AttributeType::SimpleProperty, 255.0f); + AddAttribute(tagConfig, &effect->gamma, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &effect->outputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->outputWhite, AttributeType::SimpleProperty, 255.0f); + // Red + AddAttribute(tagConfig, &effect->redInputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->redInputWhite, AttributeType::SimpleProperty, 255.0f); + AddAttribute(tagConfig, &effect->redGamma, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &effect->redOutputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->redOutputWhite, AttributeType::SimpleProperty, 255.0f); + // Green + AddAttribute(tagConfig, &effect->greenInputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->greenInputWhite, AttributeType::SimpleProperty, 255.0f); + AddAttribute(tagConfig, &effect->greenGamma, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &effect->greenOutputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->greenOutputWhite, AttributeType::SimpleProperty, 255.0f); + // Blue + AddAttribute(tagConfig, &effect->blueInputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->blueInputWhite, AttributeType::SimpleProperty, 255.0f); + AddAttribute(tagConfig, &effect->blueGamma, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &effect->blueOutputBlack, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->blueOutputWhite, AttributeType::SimpleProperty, 255.0f); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/effects/MosaicEffect.cpp b/src/codec/tags/effects/MosaicEffect.cpp index 5d594dd95c..3669787454 100644 --- a/src/codec/tags/effects/MosaicEffect.cpp +++ b/src/codec/tags/effects/MosaicEffect.cpp @@ -21,13 +21,13 @@ namespace pag { std::unique_ptr MosaicEffectTag(MosaicEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::MosaicEffect); - AddAttribute(tagConfig, &effect->horizontalBlocks, AttributeType::SimpleProperty, - static_cast(10)); - AddAttribute(tagConfig, &effect->verticalBlocks, AttributeType::SimpleProperty, - static_cast(10)); - AddAttribute(tagConfig, &effect->sharpColors, AttributeType::DiscreteProperty, false); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::MosaicEffect); + AddAttribute(tagConfig, &effect->horizontalBlocks, AttributeType::SimpleProperty, + static_cast(10)); + AddAttribute(tagConfig, &effect->verticalBlocks, AttributeType::SimpleProperty, + static_cast(10)); + AddAttribute(tagConfig, &effect->sharpColors, AttributeType::DiscreteProperty, false); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/effects/MotionTileEffect.cpp b/src/codec/tags/effects/MotionTileEffect.cpp index 353b05e69d..4e4856b40b 100644 --- a/src/codec/tags/effects/MotionTileEffect.cpp +++ b/src/codec/tags/effects/MotionTileEffect.cpp @@ -21,17 +21,17 @@ namespace pag { std::unique_ptr MotionTileEffectTag(MotionTileEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::MotionTileEffect); - AddAttribute(tagConfig, &effect->tileCenter, AttributeType::SpatialProperty, - Point::Make(640, 360)); - AddAttribute(tagConfig, &effect->tileWidth, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &effect->tileHeight, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &effect->outputWidth, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &effect->outputHeight, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &effect->mirrorEdges, AttributeType::DiscreteProperty, false); - AddAttribute(tagConfig, &effect->phase, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &effect->horizontalPhaseShift, AttributeType::DiscreteProperty, false); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::MotionTileEffect); + AddAttribute(tagConfig, &effect->tileCenter, AttributeType::SpatialProperty, + Point::Make(640, 360)); + AddAttribute(tagConfig, &effect->tileWidth, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &effect->tileHeight, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &effect->outputWidth, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &effect->outputHeight, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &effect->mirrorEdges, AttributeType::DiscreteProperty, false); + AddAttribute(tagConfig, &effect->phase, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &effect->horizontalPhaseShift, AttributeType::DiscreteProperty, false); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/effects/RadialBlurEffect.cpp b/src/codec/tags/effects/RadialBlurEffect.cpp index 7e3778e5de..dbd6fdf394 100644 --- a/src/codec/tags/effects/RadialBlurEffect.cpp +++ b/src/codec/tags/effects/RadialBlurEffect.cpp @@ -21,14 +21,14 @@ namespace pag { std::unique_ptr RadialBlurEffectTag(RadialBlurEffect* effect) { - auto tagConfig = new BlockConfig(TagCode::RadialBlurEffect); - AddAttribute(tagConfig, &effect->amount, AttributeType::SimpleProperty, 10.0f); - AddAttribute(tagConfig, &effect->center, AttributeType::SpatialProperty, - Point::Make(640.0f, 360.0f)); - AddAttribute(tagConfig, &effect->mode, AttributeType::DiscreteProperty, RadialBlurMode::Spin); - AddAttribute(tagConfig, &effect->antialias, AttributeType::DiscreteProperty, - RadialBlurAntialias::Low); - EffectCompositingOptionTag(tagConfig, effect); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::RadialBlurEffect); + AddAttribute(tagConfig, &effect->amount, AttributeType::SimpleProperty, 10.0f); + AddAttribute(tagConfig, &effect->center, AttributeType::SpatialProperty, + Point::Make(640.0f, 360.0f)); + AddAttribute(tagConfig, &effect->mode, AttributeType::DiscreteProperty, RadialBlurMode::Spin); + AddAttribute(tagConfig, &effect->antialias, AttributeType::DiscreteProperty, + RadialBlurAntialias::Low); + EffectCompositingOptionTag(tagConfig, effect); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/layerStyles/DropShadowStyle.cpp b/src/codec/tags/layerStyles/DropShadowStyle.cpp index 43cc0f1e5b..483e61b5d9 100644 --- a/src/codec/tags/layerStyles/DropShadowStyle.cpp +++ b/src/codec/tags/layerStyles/DropShadowStyle.cpp @@ -20,13 +20,13 @@ namespace pag { std::unique_ptr DropShadowStyleTag(DropShadowStyle* style) { - auto tagConfig = new BlockConfig(TagCode::DropShadowStyle); - AddAttribute(tagConfig, &style->blendMode, AttributeType::DiscreteProperty, BlendMode::Normal); - AddAttribute(tagConfig, &style->color, AttributeType::SimpleProperty, Black); - AddAttribute(tagConfig, &style->opacity, AttributeType::SimpleProperty, (Opacity)191); - AddAttribute(tagConfig, &style->angle, AttributeType::SimpleProperty, 120.0f); - AddAttribute(tagConfig, &style->distance, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &style->size, AttributeType::DiscreteProperty, 5.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::DropShadowStyle); + AddAttribute(tagConfig, &style->blendMode, AttributeType::DiscreteProperty, BlendMode::Normal); + AddAttribute(tagConfig, &style->color, AttributeType::SimpleProperty, Black); + AddAttribute(tagConfig, &style->opacity, AttributeType::SimpleProperty, (Opacity)191); + AddAttribute(tagConfig, &style->angle, AttributeType::SimpleProperty, 120.0f); + AddAttribute(tagConfig, &style->distance, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &style->size, AttributeType::DiscreteProperty, 5.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/layerStyles/DropShadowStyleV2.cpp b/src/codec/tags/layerStyles/DropShadowStyleV2.cpp index 6710106326..6337d388ae 100644 --- a/src/codec/tags/layerStyles/DropShadowStyleV2.cpp +++ b/src/codec/tags/layerStyles/DropShadowStyleV2.cpp @@ -20,14 +20,14 @@ namespace pag { std::unique_ptr DropShadowStyleTagV2(DropShadowStyle* style) { - auto tagConfig = new BlockConfig(TagCode::DropShadowStyleV2); - AddAttribute(tagConfig, &style->blendMode, AttributeType::DiscreteProperty, BlendMode::Normal); - AddAttribute(tagConfig, &style->color, AttributeType::SimpleProperty, Black); - AddAttribute(tagConfig, &style->opacity, AttributeType::SimpleProperty, (Opacity)191); - AddAttribute(tagConfig, &style->angle, AttributeType::SimpleProperty, 120.0f); - AddAttribute(tagConfig, &style->distance, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &style->size, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &style->spread, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::DropShadowStyleV2); + AddAttribute(tagConfig, &style->blendMode, AttributeType::DiscreteProperty, BlendMode::Normal); + AddAttribute(tagConfig, &style->color, AttributeType::SimpleProperty, Black); + AddAttribute(tagConfig, &style->opacity, AttributeType::SimpleProperty, (Opacity)191); + AddAttribute(tagConfig, &style->angle, AttributeType::SimpleProperty, 120.0f); + AddAttribute(tagConfig, &style->distance, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &style->size, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &style->spread, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/shapes/Dashes.cpp b/src/codec/tags/shapes/Dashes.cpp index d61c236a75..6857b6e92a 100644 --- a/src/codec/tags/shapes/Dashes.cpp +++ b/src/codec/tags/shapes/Dashes.cpp @@ -23,41 +23,41 @@ static const AttributeConfig dashOffsetConfig = {AttributeType::SimplePro static const AttributeConfig dashConfig = {AttributeType::SimpleProperty, 10.0f}; Property* ReadDashes(DecodeStream* stream, std::vector*>& dashes) { - stream->alignWithBytes(); - uint64_t dashLength = stream->readUBits(3) + 1; - auto dashOffsetFlag = ReadAttributeFlag(stream, &dashOffsetConfig); - std::vector dashFlags; - for (uint64_t i = 0; i < dashLength; i++) { - auto flag = ReadAttributeFlag(stream, &dashConfig); - dashFlags.push_back(flag); - } - Property* dashOffset = nullptr; - dashOffsetConfig.readAttribute(stream, dashOffsetFlag, &dashOffset); - for (uint64_t i = 0; i < dashLength; i++) { - Property* dash = nullptr; - dashConfig.readAttribute(stream, dashFlags[i], &dash); - dashes.push_back(dash); - } - return dashOffset; + stream->alignWithBytes(); + uint64_t dashLength = stream->readUBits(3) + 1; + auto dashOffsetFlag = ReadAttributeFlag(stream, &dashOffsetConfig); + std::vector dashFlags; + for (uint64_t i = 0; i < dashLength; i++) { + auto flag = ReadAttributeFlag(stream, &dashConfig); + dashFlags.push_back(flag); + } + Property* dashOffset = nullptr; + dashOffsetConfig.readAttribute(stream, dashOffsetFlag, &dashOffset); + for (uint64_t i = 0; i < dashLength; i++) { + Property* dash = nullptr; + dashConfig.readAttribute(stream, dashFlags[i], &dash); + dashes.push_back(dash); + } + return dashOffset; } void WriteDashes(EncodeStream* stream, std::vector*>& dashes, Property* dashOffset) { - if (dashes.empty()) { - return; - } - stream->alignWithBytes(); - EncodeStream contentBytes(stream->context); + if (dashes.empty()) { + return; + } + stream->alignWithBytes(); + EncodeStream contentBytes(stream->context); - auto dashLength = static_cast(dashes.size()); - if (dashLength > 6) { - dashLength = 6; - } - stream->writeUBits(dashLength - 1, 3); - dashOffsetConfig.writeAttribute(stream, &contentBytes, &dashOffset); - for (uint32_t i = 0; i < dashLength; i++) { - dashConfig.writeAttribute(stream, &contentBytes, &(dashes[i])); - } - stream->writeBytes(&contentBytes); + auto dashLength = static_cast(dashes.size()); + if (dashLength > 6) { + dashLength = 6; + } + stream->writeUBits(dashLength - 1, 3); + dashOffsetConfig.writeAttribute(stream, &contentBytes, &dashOffset); + for (uint32_t i = 0; i < dashLength; i++) { + dashConfig.writeAttribute(stream, &contentBytes, &(dashes[i])); + } + stream->writeBytes(&contentBytes); } } // namespace pag diff --git a/src/codec/tags/shapes/Ellipse.cpp b/src/codec/tags/shapes/Ellipse.cpp index fde63c61d3..a7db3b5aeb 100644 --- a/src/codec/tags/shapes/Ellipse.cpp +++ b/src/codec/tags/shapes/Ellipse.cpp @@ -20,11 +20,11 @@ namespace pag { std::unique_ptr EllipseTag(EllipseElement* shape) { - auto tagConfig = new BlockConfig(TagCode::Ellipse); - AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); - AddAttribute(tagConfig, &shape->size, AttributeType::MultiDimensionProperty, - Point::Make(100, 100)); - AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::Ellipse); + AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); + AddAttribute(tagConfig, &shape->size, AttributeType::MultiDimensionProperty, + Point::Make(100, 100)); + AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/Fill.cpp b/src/codec/tags/shapes/Fill.cpp index 2fe75ad2e2..0adc7ea8a7 100644 --- a/src/codec/tags/shapes/Fill.cpp +++ b/src/codec/tags/shapes/Fill.cpp @@ -20,13 +20,13 @@ namespace pag { std::unique_ptr FillTag(FillElement* shape) { - auto tagConfig = new BlockConfig(TagCode::Fill); - AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &shape->composite, AttributeType::Value, - CompositeOrder::BelowPreviousInSameGroup); - AddAttribute(tagConfig, &shape->fillRule, AttributeType::Value, FillRule::NonZeroWinding); - AddAttribute(tagConfig, &shape->color, AttributeType::SimpleProperty, Red); - AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::Fill); + AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &shape->composite, AttributeType::Value, + CompositeOrder::BelowPreviousInSameGroup); + AddAttribute(tagConfig, &shape->fillRule, AttributeType::Value, FillRule::NonZeroWinding); + AddAttribute(tagConfig, &shape->color, AttributeType::SimpleProperty, Red); + AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/Gradient.cpp b/src/codec/tags/shapes/Gradient.cpp index 6f3e899db7..fcf9142180 100644 --- a/src/codec/tags/shapes/Gradient.cpp +++ b/src/codec/tags/shapes/Gradient.cpp @@ -21,48 +21,48 @@ namespace pag { static void ReadStrokeDashes(DecodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - shape->dashOffset = ReadDashes(stream, shape->dashes); + auto shape = reinterpret_cast(target); + shape->dashOffset = ReadDashes(stream, shape->dashes); } static bool WriteStrokeDashes(EncodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - WriteDashes(stream, shape->dashes, shape->dashOffset); - return !shape->dashes.empty(); + auto shape = reinterpret_cast(target); + WriteDashes(stream, shape->dashes, shape->dashOffset); + return !shape->dashes.empty(); } template void AddGradientCommonTags(BlockConfig* tagConfig, T* shape) { - AddAttribute(tagConfig, &shape->fillType, AttributeType::Value, GradientFillType::Linear); - AddAttribute(tagConfig, &shape->startPoint, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &shape->endPoint, AttributeType::SpatialProperty, Point::Make(100, 0)); - AddAttribute(tagConfig, &shape->colors, AttributeType::SimpleProperty, - GradientColorHandle(new GradientColor())); - AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); + AddAttribute(tagConfig, &shape->fillType, AttributeType::Value, GradientFillType::Linear); + AddAttribute(tagConfig, &shape->startPoint, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &shape->endPoint, AttributeType::SpatialProperty, Point::Make(100, 0)); + AddAttribute(tagConfig, &shape->colors, AttributeType::SimpleProperty, + GradientColorHandle(new GradientColor())); + AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); } std::unique_ptr GradientStrokeTag(GradientStrokeElement* shape) { - auto tagConfig = new BlockConfig(TagCode::GradientStroke); - AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &shape->composite, AttributeType::Value, - CompositeOrder::BelowPreviousInSameGroup); - AddGradientCommonTags(tagConfig, shape); - AddAttribute(tagConfig, &shape->strokeWidth, AttributeType::SimpleProperty, 2.0f); - AddAttribute(tagConfig, &shape->lineCap, AttributeType::Value, LineCap::Butt); - AddAttribute(tagConfig, &shape->lineJoin, AttributeType::Value, LineJoin::Miter); - AddAttribute(tagConfig, &shape->miterLimit, AttributeType::SimpleProperty, 4.0f); - AddCustomAttribute(tagConfig, shape, ReadStrokeDashes, WriteStrokeDashes); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::GradientStroke); + AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &shape->composite, AttributeType::Value, + CompositeOrder::BelowPreviousInSameGroup); + AddGradientCommonTags(tagConfig, shape); + AddAttribute(tagConfig, &shape->strokeWidth, AttributeType::SimpleProperty, 2.0f); + AddAttribute(tagConfig, &shape->lineCap, AttributeType::Value, LineCap::Butt); + AddAttribute(tagConfig, &shape->lineJoin, AttributeType::Value, LineJoin::Miter); + AddAttribute(tagConfig, &shape->miterLimit, AttributeType::SimpleProperty, 4.0f); + AddCustomAttribute(tagConfig, shape, ReadStrokeDashes, WriteStrokeDashes); + return std::unique_ptr(tagConfig); } std::unique_ptr GradientFillTag(GradientFillElement* shape) { - auto tagConfig = new BlockConfig(TagCode::GradientFill); - AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &shape->composite, AttributeType::Value, - CompositeOrder::BelowPreviousInSameGroup); - AddAttribute(tagConfig, &shape->fillRule, AttributeType::Value, FillRule::NonZeroWinding); - AddGradientCommonTags(tagConfig, shape); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::GradientFill); + AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &shape->composite, AttributeType::Value, + CompositeOrder::BelowPreviousInSameGroup); + AddAttribute(tagConfig, &shape->fillRule, AttributeType::Value, FillRule::NonZeroWinding); + AddGradientCommonTags(tagConfig, shape); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/MergePaths.cpp b/src/codec/tags/shapes/MergePaths.cpp index ed89328c35..3eab958bbf 100644 --- a/src/codec/tags/shapes/MergePaths.cpp +++ b/src/codec/tags/shapes/MergePaths.cpp @@ -20,8 +20,8 @@ namespace pag { std::unique_ptr MergePathsTag(MergePathsElement* shape) { - auto tagConfig = new BlockConfig(TagCode::MergePaths); - AddAttribute(tagConfig, &shape->mode, AttributeType::FixedValue, MergePathsMode::Add); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::MergePaths); + AddAttribute(tagConfig, &shape->mode, AttributeType::FixedValue, MergePathsMode::Add); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/PolyStar.cpp b/src/codec/tags/shapes/PolyStar.cpp index dea557bb9f..4c7d844578 100644 --- a/src/codec/tags/shapes/PolyStar.cpp +++ b/src/codec/tags/shapes/PolyStar.cpp @@ -20,16 +20,16 @@ namespace pag { std::unique_ptr PolyStarTag(PolyStarElement* shape) { - auto tagConfig = new BlockConfig(TagCode::PolyStar); - AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); - AddAttribute(tagConfig, &shape->polyType, AttributeType::Value, PolyStarType::Star); - AddAttribute(tagConfig, &shape->points, AttributeType::SimpleProperty, 5.0f); - AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &shape->rotation, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &shape->innerRadius, AttributeType::SimpleProperty, 50.0f); - AddAttribute(tagConfig, &shape->outerRadius, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &shape->innerRoundness, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &shape->outerRoundness, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::PolyStar); + AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); + AddAttribute(tagConfig, &shape->polyType, AttributeType::Value, PolyStarType::Star); + AddAttribute(tagConfig, &shape->points, AttributeType::SimpleProperty, 5.0f); + AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &shape->rotation, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &shape->innerRadius, AttributeType::SimpleProperty, 50.0f); + AddAttribute(tagConfig, &shape->outerRadius, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &shape->innerRoundness, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &shape->outerRoundness, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/Rectangle.cpp b/src/codec/tags/shapes/Rectangle.cpp index 61a98c07c1..617b6b512f 100644 --- a/src/codec/tags/shapes/Rectangle.cpp +++ b/src/codec/tags/shapes/Rectangle.cpp @@ -20,12 +20,12 @@ namespace pag { std::unique_ptr RectangleTag(RectangleElement* shape) { - auto tagConfig = new BlockConfig(TagCode::Rectangle); - AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); - AddAttribute(tagConfig, &shape->size, AttributeType::MultiDimensionProperty, - Point::Make(100, 100)); - AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &shape->roundness, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::Rectangle); + AddAttribute(tagConfig, &shape->reversed, AttributeType::BitFlag, false); + AddAttribute(tagConfig, &shape->size, AttributeType::MultiDimensionProperty, + Point::Make(100, 100)); + AddAttribute(tagConfig, &shape->position, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &shape->roundness, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/Repeater.cpp b/src/codec/tags/shapes/Repeater.cpp index 370eae2062..7ea7d97e35 100644 --- a/src/codec/tags/shapes/Repeater.cpp +++ b/src/codec/tags/shapes/Repeater.cpp @@ -20,22 +20,22 @@ namespace pag { std::unique_ptr RepeaterTag(RepeaterElement* shape) { - if (shape->transform == nullptr) { - shape->transform = new RepeaterTransform(); - } - auto transform = shape->transform; - auto tagConfig = new BlockConfig(TagCode::Repeater); - AddAttribute(tagConfig, &shape->composite, AttributeType::Value, RepeaterOrder::Below); - AddAttribute(tagConfig, &shape->copies, AttributeType::SimpleProperty, 3.0f); - AddAttribute(tagConfig, &shape->offset, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, - Point::Make(100, 100)); - AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, - Point::Make(1, 1)); - AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->startOpacity, AttributeType::SimpleProperty, Opaque); - AddAttribute(tagConfig, &transform->endOpacity, AttributeType::SimpleProperty, Opaque); - return std::unique_ptr(tagConfig); + if (shape->transform == nullptr) { + shape->transform = new RepeaterTransform(); + } + auto transform = shape->transform; + auto tagConfig = new BlockConfig(TagCode::Repeater); + AddAttribute(tagConfig, &shape->composite, AttributeType::Value, RepeaterOrder::Below); + AddAttribute(tagConfig, &shape->copies, AttributeType::SimpleProperty, 3.0f); + AddAttribute(tagConfig, &shape->offset, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, + Point::Make(100, 100)); + AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, + Point::Make(1, 1)); + AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->startOpacity, AttributeType::SimpleProperty, Opaque); + AddAttribute(tagConfig, &transform->endOpacity, AttributeType::SimpleProperty, Opaque); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/RoundCorners.cpp b/src/codec/tags/shapes/RoundCorners.cpp index 0776f78781..032a6173ab 100644 --- a/src/codec/tags/shapes/RoundCorners.cpp +++ b/src/codec/tags/shapes/RoundCorners.cpp @@ -20,8 +20,8 @@ namespace pag { std::unique_ptr RoundCornersTag(RoundCornersElement* shape) { - auto tagConfig = new BlockConfig(TagCode::RoundCorners); - AddAttribute(tagConfig, &shape->radius, AttributeType::SimpleProperty, 10.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::RoundCorners); + AddAttribute(tagConfig, &shape->radius, AttributeType::SimpleProperty, 10.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/ShapeGroup.cpp b/src/codec/tags/shapes/ShapeGroup.cpp index 27e1446651..d4f6da22ed 100644 --- a/src/codec/tags/shapes/ShapeGroup.cpp +++ b/src/codec/tags/shapes/ShapeGroup.cpp @@ -22,39 +22,39 @@ namespace pag { void ReadTagsOfShapeGroup(DecodeStream* stream, TagCode code, std::vector* contents) { - ReadShape(stream, code, contents); + ReadShape(stream, code, contents); } void ReadShapeGroupElements(DecodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - ReadTags(stream, &(shape->elements), ReadTagsOfShapeGroup); + auto shape = reinterpret_cast(target); + ReadTags(stream, &(shape->elements), ReadTagsOfShapeGroup); } bool WriteShapeGroupElements(EncodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - if (!shape->elements.empty()) { - WriteShape(stream, &(shape->elements)); - WriteEndTag(stream); - } - return !shape->elements.empty(); + auto shape = reinterpret_cast(target); + if (!shape->elements.empty()) { + WriteShape(stream, &(shape->elements)); + WriteEndTag(stream); + } + return !shape->elements.empty(); } std::unique_ptr ShapeGroupTag(ShapeGroupElement* shape) { - if (shape->transform == nullptr) { - shape->transform = new ShapeTransform(); - } - auto transform = shape->transform; - auto tagConfig = new BlockConfig(TagCode::ShapeGroup); - AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, Point::Zero()); - AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, - Point::Make(1, 1)); - AddAttribute(tagConfig, &transform->skew, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->skewAxis, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &transform->opacity, AttributeType::SimpleProperty, Opaque); - AddCustomAttribute(tagConfig, shape, ReadShapeGroupElements, WriteShapeGroupElements); - return std::unique_ptr(tagConfig); + if (shape->transform == nullptr) { + shape->transform = new ShapeTransform(); + } + auto transform = shape->transform; + auto tagConfig = new BlockConfig(TagCode::ShapeGroup); + AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &transform->anchorPoint, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &transform->position, AttributeType::SpatialProperty, Point::Zero()); + AddAttribute(tagConfig, &transform->scale, AttributeType::MultiDimensionProperty, + Point::Make(1, 1)); + AddAttribute(tagConfig, &transform->skew, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->skewAxis, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->rotation, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &transform->opacity, AttributeType::SimpleProperty, Opaque); + AddCustomAttribute(tagConfig, shape, ReadShapeGroupElements, WriteShapeGroupElements); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/ShapePath.cpp b/src/codec/tags/shapes/ShapePath.cpp index 4e0cc9146f..36d70b8d8d 100644 --- a/src/codec/tags/shapes/ShapePath.cpp +++ b/src/codec/tags/shapes/ShapePath.cpp @@ -20,9 +20,9 @@ namespace pag { std::unique_ptr ShapePathTag(ShapePathElement* shape) { - auto tagConfig = new BlockConfig(TagCode::ShapePath); - AddAttribute(tagConfig, &shape->shapePath, AttributeType::SimpleProperty, - PathHandle(new PathData())); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::ShapePath); + AddAttribute(tagConfig, &shape->shapePath, AttributeType::SimpleProperty, + PathHandle(new PathData())); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/Stroke.cpp b/src/codec/tags/shapes/Stroke.cpp index d7d97148b6..0d16800f1b 100644 --- a/src/codec/tags/shapes/Stroke.cpp +++ b/src/codec/tags/shapes/Stroke.cpp @@ -21,28 +21,28 @@ namespace pag { static void ReadStrokeDashes(DecodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - shape->dashOffset = ReadDashes(stream, shape->dashes); + auto shape = reinterpret_cast(target); + shape->dashOffset = ReadDashes(stream, shape->dashes); } static bool WriteStrokeDashes(EncodeStream* stream, void* target) { - auto shape = reinterpret_cast(target); - WriteDashes(stream, shape->dashes, shape->dashOffset); - return !shape->dashes.empty(); + auto shape = reinterpret_cast(target); + WriteDashes(stream, shape->dashes, shape->dashOffset); + return !shape->dashes.empty(); } std::unique_ptr StrokeTag(StrokeElement* shape) { - auto tagConfig = new BlockConfig(TagCode::Stroke); - AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); - AddAttribute(tagConfig, &shape->composite, AttributeType::Value, - CompositeOrder::BelowPreviousInSameGroup); - AddAttribute(tagConfig, &shape->lineCap, AttributeType::Value, LineCap::Butt); - AddAttribute(tagConfig, &shape->lineJoin, AttributeType::Value, LineJoin::Miter); - AddAttribute(tagConfig, &shape->miterLimit, AttributeType::SimpleProperty, 4.0f); - AddAttribute(tagConfig, &shape->color, AttributeType::SimpleProperty, White); - AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); - AddAttribute(tagConfig, &shape->strokeWidth, AttributeType::SimpleProperty, 2.0f); - AddCustomAttribute(tagConfig, shape, ReadStrokeDashes, WriteStrokeDashes); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::Stroke); + AddAttribute(tagConfig, &shape->blendMode, AttributeType::Value, BlendMode::Normal); + AddAttribute(tagConfig, &shape->composite, AttributeType::Value, + CompositeOrder::BelowPreviousInSameGroup); + AddAttribute(tagConfig, &shape->lineCap, AttributeType::Value, LineCap::Butt); + AddAttribute(tagConfig, &shape->lineJoin, AttributeType::Value, LineJoin::Miter); + AddAttribute(tagConfig, &shape->miterLimit, AttributeType::SimpleProperty, 4.0f); + AddAttribute(tagConfig, &shape->color, AttributeType::SimpleProperty, White); + AddAttribute(tagConfig, &shape->opacity, AttributeType::SimpleProperty, Opaque); + AddAttribute(tagConfig, &shape->strokeWidth, AttributeType::SimpleProperty, 2.0f); + AddCustomAttribute(tagConfig, shape, ReadStrokeDashes, WriteStrokeDashes); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/shapes/TrimPaths.cpp b/src/codec/tags/shapes/TrimPaths.cpp index e2a8cdd345..102d25d187 100644 --- a/src/codec/tags/shapes/TrimPaths.cpp +++ b/src/codec/tags/shapes/TrimPaths.cpp @@ -20,12 +20,12 @@ namespace pag { std::unique_ptr TrimPathsTag(TrimPathsElement* shape) { - auto tagConfig = new BlockConfig(TagCode::TrimPaths); - AddAttribute(tagConfig, &shape->start, AttributeType::SimpleProperty, 0.0f); - // The default value of the end property should be 1.0f, but for backward compatibility we do not change it. - AddAttribute(tagConfig, &shape->end, AttributeType::SimpleProperty, 100.0f); - AddAttribute(tagConfig, &shape->offset, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &shape->trimType, AttributeType::Value, TrimPathsType::Simultaneously); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TrimPaths); + AddAttribute(tagConfig, &shape->start, AttributeType::SimpleProperty, 0.0f); + // The default value of the end property should be 1.0f, but for backward compatibility we do not change it. + AddAttribute(tagConfig, &shape->end, AttributeType::SimpleProperty, 100.0f); + AddAttribute(tagConfig, &shape->offset, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &shape->trimType, AttributeType::Value, TrimPathsType::Simultaneously); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/text/TextAnimatorTag.cpp b/src/codec/tags/text/TextAnimatorTag.cpp index 817dfe8d88..8a7e608f56 100644 --- a/src/codec/tags/text/TextAnimatorTag.cpp +++ b/src/codec/tags/text/TextAnimatorTag.cpp @@ -24,211 +24,212 @@ namespace pag { static std::unique_ptr TextAnimatorTrackingTypeTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesTrackingType); - AddAttribute(tagConfig, &properties->trackingType, AttributeType::DiscreteProperty, - TextAnimatorTrackingType::BeforeAndAfter); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesTrackingType); + AddAttribute(tagConfig, &properties->trackingType, AttributeType::DiscreteProperty, + TextAnimatorTrackingType::BeforeAndAfter); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorTrackingAmountTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesTrackingAmount); - AddAttribute(tagConfig, &properties->trackingAmount, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesTrackingAmount); + AddAttribute(tagConfig, &properties->trackingAmount, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorPositionTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesPosition); - AddAttribute(tagConfig, &properties->position, AttributeType::SpatialProperty, Point::Zero()); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesPosition); + AddAttribute(tagConfig, &properties->position, AttributeType::SpatialProperty, Point::Zero()); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorScaleTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesScale); - AddAttribute(tagConfig, &properties->scale, AttributeType::MultiDimensionProperty, - Point::Make(1, 1)); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesScale); + AddAttribute(tagConfig, &properties->scale, AttributeType::MultiDimensionProperty, + Point::Make(1, 1)); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorRotationTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesRotation); - AddAttribute(tagConfig, &properties->rotation, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesRotation); + AddAttribute(tagConfig, &properties->rotation, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorOpacityTag( TextAnimatorTypographyProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesOpacity); - AddAttribute(tagConfig, &properties->opacity, AttributeType::SimpleProperty, Opaque); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesOpacity); + AddAttribute(tagConfig, &properties->opacity, AttributeType::SimpleProperty, Opaque); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorFillColorTag( TextAnimatorColorProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesFillColor); - AddAttribute(tagConfig, &properties->fillColor, AttributeType::SimpleProperty, Red); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesFillColor); + AddAttribute(tagConfig, &properties->fillColor, AttributeType::SimpleProperty, Red); + return std::unique_ptr(tagConfig); } static std::unique_ptr TextAnimatorStrokeColorTag( TextAnimatorColorProperties* properties) { - auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesStrokeColor); - AddAttribute(tagConfig, &properties->strokeColor, AttributeType::SimpleProperty, Red); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextAnimatorPropertiesStrokeColor); + AddAttribute(tagConfig, &properties->strokeColor, AttributeType::SimpleProperty, Red); + return std::unique_ptr(tagConfig); } static void CheckTypographyProperties(TextAnimator* animator) { - if (animator->typographyProperties == nullptr) { - animator->typographyProperties = new TextAnimatorTypographyProperties(); - } + if (animator->typographyProperties == nullptr) { + animator->typographyProperties = new TextAnimatorTypographyProperties(); + } } static void CheckColorProperties(TextAnimator* animator) { - if (animator->colorProperties == nullptr) { - animator->colorProperties = new TextAnimatorColorProperties(); - } + if (animator->colorProperties == nullptr) { + animator->colorProperties = new TextAnimatorColorProperties(); + } } static void ReadTag_TextRangeSelector(DecodeStream* stream, TextAnimator* animator) { - auto selector = new TextRangeSelector(); - ReadTagBlock(stream, selector, TextRangeSelectorTag); - animator->selectors.push_back(selector); + auto selector = new TextRangeSelector(); + ReadTagBlock(stream, selector, TextRangeSelectorTag); + animator->selectors.push_back(selector); } static void ReadTag_TextWigglySelector(DecodeStream* stream, TextAnimator* animator) { - auto selector = new TextWigglySelector(); - ReadTagBlock(stream, selector, TextWigglySelectorTag); - animator->selectors.push_back(selector); + auto selector = new TextWigglySelector(); + ReadTagBlock(stream, selector, TextWigglySelectorTag); + animator->selectors.push_back(selector); } static void ReadTag_TextAnimatorPropertiesTrackingType(DecodeStream* stream, - TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingTypeTag); + TextAnimator* animator) { + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingTypeTag); } static void ReadTag_TextAnimatorPropertiesTrackingAmount(DecodeStream* stream, - TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingAmountTag); + TextAnimator* animator) { + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingAmountTag); } static void ReadTag_TextAnimatorPropertiesPosition(DecodeStream* stream, TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorPositionTag); + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorPositionTag); } static void ReadTag_TextAnimatorPropertiesScale(DecodeStream* stream, TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorScaleTag); + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorScaleTag); } static void ReadTag_TextAnimatorPropertiesRotation(DecodeStream* stream, TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorRotationTag); + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorRotationTag); } static void ReadTag_TextAnimatorPropertiesOpacity(DecodeStream* stream, TextAnimator* animator) { - CheckTypographyProperties(animator); - ReadTagBlock(stream, animator->typographyProperties, TextAnimatorOpacityTag); + CheckTypographyProperties(animator); + ReadTagBlock(stream, animator->typographyProperties, TextAnimatorOpacityTag); } static void ReadTag_TextAnimatorPropertiesFillColor(DecodeStream* stream, TextAnimator* animator) { - CheckColorProperties(animator); - ReadTagBlock(stream, animator->colorProperties, TextAnimatorFillColorTag); + CheckColorProperties(animator); + ReadTagBlock(stream, animator->colorProperties, TextAnimatorFillColorTag); } static void ReadTag_TextAnimatorPropertiesStrokeColor(DecodeStream* stream, - TextAnimator* animator) { - CheckColorProperties(animator); - ReadTagBlock(stream, animator->colorProperties, TextAnimatorStrokeColorTag); + TextAnimator* animator) { + CheckColorProperties(animator); + ReadTagBlock(stream, animator->colorProperties, TextAnimatorStrokeColorTag); } using ReadTextAnimatorHandler = void(DecodeStream* stream, TextAnimator* animator); static const std::unordered_map, EnumClassHash> - elementHandlers = { - {TagCode::TextRangeSelector, ReadTag_TextRangeSelector}, - {TagCode::TextWigglySelector, ReadTag_TextWigglySelector}, - {TagCode::TextAnimatorPropertiesTrackingType, ReadTag_TextAnimatorPropertiesTrackingType}, - {TagCode::TextAnimatorPropertiesTrackingAmount, - ReadTag_TextAnimatorPropertiesTrackingAmount}, - {TagCode::TextAnimatorPropertiesPosition, ReadTag_TextAnimatorPropertiesPosition}, - {TagCode::TextAnimatorPropertiesScale, ReadTag_TextAnimatorPropertiesScale}, - {TagCode::TextAnimatorPropertiesRotation, ReadTag_TextAnimatorPropertiesRotation}, - {TagCode::TextAnimatorPropertiesOpacity, ReadTag_TextAnimatorPropertiesOpacity}, - {TagCode::TextAnimatorPropertiesFillColor, ReadTag_TextAnimatorPropertiesFillColor}, - {TagCode::TextAnimatorPropertiesStrokeColor, ReadTag_TextAnimatorPropertiesStrokeColor}, +elementHandlers = { + {TagCode::TextRangeSelector, ReadTag_TextRangeSelector}, + {TagCode::TextWigglySelector, ReadTag_TextWigglySelector}, + {TagCode::TextAnimatorPropertiesTrackingType, ReadTag_TextAnimatorPropertiesTrackingType}, + { TagCode::TextAnimatorPropertiesTrackingAmount, + ReadTag_TextAnimatorPropertiesTrackingAmount + }, + {TagCode::TextAnimatorPropertiesPosition, ReadTag_TextAnimatorPropertiesPosition}, + {TagCode::TextAnimatorPropertiesScale, ReadTag_TextAnimatorPropertiesScale}, + {TagCode::TextAnimatorPropertiesRotation, ReadTag_TextAnimatorPropertiesRotation}, + {TagCode::TextAnimatorPropertiesOpacity, ReadTag_TextAnimatorPropertiesOpacity}, + {TagCode::TextAnimatorPropertiesFillColor, ReadTag_TextAnimatorPropertiesFillColor}, + {TagCode::TextAnimatorPropertiesStrokeColor, ReadTag_TextAnimatorPropertiesStrokeColor}, }; static void ReadTagsOfTextAnimator(DecodeStream* stream, TagCode code, TextAnimator* animator) { - auto iter = elementHandlers.find(code); - if (iter == elementHandlers.end()) { - return; - } - iter->second(stream, animator); + auto iter = elementHandlers.find(code); + if (iter == elementHandlers.end()) { + return; + } + iter->second(stream, animator); } void ReadTextAnimator(DecodeStream* stream, TextLayer* layer) { - TextAnimator* animator = new TextAnimator(); + TextAnimator* animator = new TextAnimator(); - ReadTags(stream, animator, ReadTagsOfTextAnimator); + ReadTags(stream, animator, ReadTagsOfTextAnimator); - layer->animators.push_back(animator); + layer->animators.push_back(animator); } static void WriteTextSelectors(EncodeStream* stream, const TextAnimator* animator) { - for (auto& selector : animator->selectors) { - if (selector->type() == TextSelectorType::Range) { - WriteTagBlock(stream, static_cast(selector), TextRangeSelectorTag); - } else if (selector->type() == TextSelectorType::Wiggly) { - WriteTagBlock(stream, static_cast(selector), TextWigglySelectorTag); + for (auto& selector : animator->selectors) { + if (selector->type() == TextSelectorType::Range) { + WriteTagBlock(stream, static_cast(selector), TextRangeSelectorTag); + } else if (selector->type() == TextSelectorType::Wiggly) { + WriteTagBlock(stream, static_cast(selector), TextWigglySelectorTag); + } } - } } static void WriteColorProperties(EncodeStream* stream, const TextAnimator* animator) { - if (animator->colorProperties != nullptr) { - if (animator->colorProperties->fillColor != nullptr) { - WriteTagBlock(stream, animator->colorProperties, TextAnimatorFillColorTag); + if (animator->colorProperties != nullptr) { + if (animator->colorProperties->fillColor != nullptr) { + WriteTagBlock(stream, animator->colorProperties, TextAnimatorFillColorTag); + } + if (animator->colorProperties->strokeColor != nullptr) { + WriteTagBlock(stream, animator->colorProperties, TextAnimatorStrokeColorTag); + } } - if (animator->colorProperties->strokeColor != nullptr) { - WriteTagBlock(stream, animator->colorProperties, TextAnimatorStrokeColorTag); - } - } } static void WriteTypographyProperties(EncodeStream* stream, const TextAnimator* animator) { - if (animator->typographyProperties != nullptr) { - if (animator->typographyProperties->trackingType != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingTypeTag); - } - if (animator->typographyProperties->trackingAmount != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingAmountTag); - } - if (animator->typographyProperties->position != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorPositionTag); - } - if (animator->typographyProperties->scale != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorScaleTag); - } - if (animator->typographyProperties->rotation != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorRotationTag); - } - if (animator->typographyProperties->opacity != nullptr) { - WriteTagBlock(stream, animator->typographyProperties, TextAnimatorOpacityTag); + if (animator->typographyProperties != nullptr) { + if (animator->typographyProperties->trackingType != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingTypeTag); + } + if (animator->typographyProperties->trackingAmount != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorTrackingAmountTag); + } + if (animator->typographyProperties->position != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorPositionTag); + } + if (animator->typographyProperties->scale != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorScaleTag); + } + if (animator->typographyProperties->rotation != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorRotationTag); + } + if (animator->typographyProperties->opacity != nullptr) { + WriteTagBlock(stream, animator->typographyProperties, TextAnimatorOpacityTag); + } } - } } TagCode WriteTextAnimator(EncodeStream* stream, TextAnimator* animator) { - WriteTextSelectors(stream, animator); - WriteColorProperties(stream, animator); - WriteTypographyProperties(stream, animator); - WriteEndTag(stream); - return TagCode::TextAnimator; + WriteTextSelectors(stream, animator); + WriteColorProperties(stream, animator); + WriteTypographyProperties(stream, animator); + WriteEndTag(stream); + return TagCode::TextAnimator; } } // namespace pag diff --git a/src/codec/tags/text/TextMoreOption.cpp b/src/codec/tags/text/TextMoreOption.cpp index c38df8c62f..bf2c36cfbb 100644 --- a/src/codec/tags/text/TextMoreOption.cpp +++ b/src/codec/tags/text/TextMoreOption.cpp @@ -20,11 +20,11 @@ namespace pag { std::unique_ptr TextMoreOptionTag(TextMoreOptions* moreOption) { - auto tagConfig = new BlockConfig(TagCode::TextPathOption); - AddAttribute(tagConfig, &moreOption->anchorPointGrouping, AttributeType::Value, - AnchorPointGrouping::Character); - AddAttribute(tagConfig, &moreOption->groupingAlignment, AttributeType::MultiDimensionProperty, - Point::Zero()); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextPathOption); + AddAttribute(tagConfig, &moreOption->anchorPointGrouping, AttributeType::Value, + AnchorPointGrouping::Character); + AddAttribute(tagConfig, &moreOption->groupingAlignment, AttributeType::MultiDimensionProperty, + Point::Zero()); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/text/TextPathOption.cpp b/src/codec/tags/text/TextPathOption.cpp index ce97023b97..6d9096632d 100644 --- a/src/codec/tags/text/TextPathOption.cpp +++ b/src/codec/tags/text/TextPathOption.cpp @@ -20,13 +20,13 @@ namespace pag { std::unique_ptr TextPathOptionTag(TextPathOptions* pathOption) { - auto tagConfig = new BlockConfig(TagCode::TextPathOption); - AddAttribute(tagConfig, &pathOption->path, AttributeType::Value, static_cast(nullptr)); - AddAttribute(tagConfig, &pathOption->reversedPath, AttributeType::DiscreteProperty, false); - AddAttribute(tagConfig, &pathOption->perpendicularToPath, AttributeType::DiscreteProperty, true); - AddAttribute(tagConfig, &pathOption->forceAlignment, AttributeType::DiscreteProperty, false); - AddAttribute(tagConfig, &pathOption->firstMargin, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &pathOption->lastMargin, AttributeType::SimpleProperty, 0.0f); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextPathOption); + AddAttribute(tagConfig, &pathOption->path, AttributeType::Value, static_cast(nullptr)); + AddAttribute(tagConfig, &pathOption->reversedPath, AttributeType::DiscreteProperty, false); + AddAttribute(tagConfig, &pathOption->perpendicularToPath, AttributeType::DiscreteProperty, true); + AddAttribute(tagConfig, &pathOption->forceAlignment, AttributeType::DiscreteProperty, false); + AddAttribute(tagConfig, &pathOption->firstMargin, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &pathOption->lastMargin, AttributeType::SimpleProperty, 0.0f); + return std::unique_ptr(tagConfig); } } // namespace pag \ No newline at end of file diff --git a/src/codec/tags/text/TextSelector.cpp b/src/codec/tags/text/TextSelector.cpp index 906a502f61..3c1e5bf93b 100644 --- a/src/codec/tags/text/TextSelector.cpp +++ b/src/codec/tags/text/TextSelector.cpp @@ -20,45 +20,45 @@ namespace pag { std::unique_ptr TextRangeSelectorTag(TextRangeSelector* selector) { - auto tagConfig = new BlockConfig(TagCode::TextRangeSelector); + auto tagConfig = new BlockConfig(TagCode::TextRangeSelector); - AddAttribute(tagConfig, &selector->start, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->end, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &selector->offset, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->units, AttributeType::Value, - TextRangeSelectorUnits::Percentage); - AddAttribute(tagConfig, &selector->basedOn, AttributeType::Value, - TextSelectorBasedOn::Characters); - AddAttribute(tagConfig, &selector->mode, AttributeType::DiscreteProperty, TextSelectorMode::Add); - AddAttribute(tagConfig, &selector->amount, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &selector->shape, AttributeType::Value, TextRangeSelectorShape::Square); - AddAttribute(tagConfig, &selector->smoothness, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &selector->easeHigh, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->easeLow, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->randomizeOrder, AttributeType::BitFlag, false); - AddAttribute(tagConfig, &selector->randomSeed, AttributeType::SimpleProperty, - static_cast(0)); + AddAttribute(tagConfig, &selector->start, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->end, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &selector->offset, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->units, AttributeType::Value, + TextRangeSelectorUnits::Percentage); + AddAttribute(tagConfig, &selector->basedOn, AttributeType::Value, + TextSelectorBasedOn::Characters); + AddAttribute(tagConfig, &selector->mode, AttributeType::DiscreteProperty, TextSelectorMode::Add); + AddAttribute(tagConfig, &selector->amount, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &selector->shape, AttributeType::Value, TextRangeSelectorShape::Square); + AddAttribute(tagConfig, &selector->smoothness, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &selector->easeHigh, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->easeLow, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->randomizeOrder, AttributeType::BitFlag, false); + AddAttribute(tagConfig, &selector->randomSeed, AttributeType::SimpleProperty, + static_cast(0)); - return std::unique_ptr(tagConfig); + return std::unique_ptr(tagConfig); } std::unique_ptr TextWigglySelectorTag(TextWigglySelector* selector) { - auto tagConfig = new BlockConfig(TagCode::TextWigglySelector); + auto tagConfig = new BlockConfig(TagCode::TextWigglySelector); - AddAttribute(tagConfig, &selector->mode, AttributeType::DiscreteProperty, - TextSelectorMode::Intersect); - AddAttribute(tagConfig, &selector->maxAmount, AttributeType::SimpleProperty, 1.0f); - AddAttribute(tagConfig, &selector->minAmount, AttributeType::SimpleProperty, -1.0f); - AddAttribute(tagConfig, &selector->basedOn, AttributeType::Value, - TextSelectorBasedOn::Characters); - AddAttribute(tagConfig, &selector->wigglesPerSecond, AttributeType::SimpleProperty, 2.0f); - AddAttribute(tagConfig, &selector->correlation, AttributeType::SimpleProperty, 0.5f); - AddAttribute(tagConfig, &selector->temporalPhase, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->spatialPhase, AttributeType::SimpleProperty, 0.0f); - AddAttribute(tagConfig, &selector->lockDimensions, AttributeType::DiscreteProperty, false); - AddAttribute(tagConfig, &selector->randomSeed, AttributeType::SimpleProperty, - static_cast(0)); + AddAttribute(tagConfig, &selector->mode, AttributeType::DiscreteProperty, + TextSelectorMode::Intersect); + AddAttribute(tagConfig, &selector->maxAmount, AttributeType::SimpleProperty, 1.0f); + AddAttribute(tagConfig, &selector->minAmount, AttributeType::SimpleProperty, -1.0f); + AddAttribute(tagConfig, &selector->basedOn, AttributeType::Value, + TextSelectorBasedOn::Characters); + AddAttribute(tagConfig, &selector->wigglesPerSecond, AttributeType::SimpleProperty, 2.0f); + AddAttribute(tagConfig, &selector->correlation, AttributeType::SimpleProperty, 0.5f); + AddAttribute(tagConfig, &selector->temporalPhase, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->spatialPhase, AttributeType::SimpleProperty, 0.0f); + AddAttribute(tagConfig, &selector->lockDimensions, AttributeType::DiscreteProperty, false); + AddAttribute(tagConfig, &selector->randomSeed, AttributeType::SimpleProperty, + static_cast(0)); - return std::unique_ptr(tagConfig); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/tags/text/TextSource.cpp b/src/codec/tags/text/TextSource.cpp index 34c77f9b78..851a6565d6 100644 --- a/src/codec/tags/text/TextSource.cpp +++ b/src/codec/tags/text/TextSource.cpp @@ -20,31 +20,31 @@ namespace pag { std::unique_ptr TextSourceTag(TextLayer* layer) { - auto tagConfig = new BlockConfig(TagCode::TextSource); - AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, - TextDocumentHandle(new TextDocument())); - return std::unique_ptr(tagConfig); + auto tagConfig = new BlockConfig(TagCode::TextSource); + AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, + TextDocumentHandle(new TextDocument())); + return std::unique_ptr(tagConfig); } std::unique_ptr TextSourceTagV2(TextLayer* layer) { - auto tagConfig = new BlockConfig(TagCode::TextSourceV2); - auto defaultTextDocument = TextDocumentHandle(new TextDocument()); + auto tagConfig = new BlockConfig(TagCode::TextSourceV2); + auto defaultTextDocument = TextDocumentHandle(new TextDocument()); - // This is the key property that triggers tag V2. - defaultTextDocument->backgroundAlpha = 255; + // This is the key property that triggers tag V2. + defaultTextDocument->backgroundAlpha = 255; - AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, defaultTextDocument); - return std::unique_ptr(tagConfig); + AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, defaultTextDocument); + return std::unique_ptr(tagConfig); } std::unique_ptr TextSourceTagV3(TextLayer* layer) { - auto tagConfig = new BlockConfig(TagCode::TextSourceV3); - auto defaultTextDocument = TextDocumentHandle(new TextDocument()); + auto tagConfig = new BlockConfig(TagCode::TextSourceV3); + auto defaultTextDocument = TextDocumentHandle(new TextDocument()); - // This is the key property that triggers tag V3 - defaultTextDocument->direction = TextDirection::Horizontal; + // This is the key property that triggers tag V3 + defaultTextDocument->direction = TextDirection::Horizontal; - AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, defaultTextDocument); - return std::unique_ptr(tagConfig); + AddAttribute(tagConfig, &layer->sourceText, AttributeType::DiscreteProperty, defaultTextDocument); + return std::unique_ptr(tagConfig); } } // namespace pag diff --git a/src/codec/utils/ByteOrder.cpp b/src/codec/utils/ByteOrder.cpp index 8d04cb056a..89215a0e4e 100644 --- a/src/codec/utils/ByteOrder.cpp +++ b/src/codec/utils/ByteOrder.cpp @@ -20,8 +20,8 @@ namespace pag { ByteOrder EndianTest() { - int i = 1; - auto p = static_cast(static_cast(&i)); - return (*p == 1) ? ByteOrder::LittleEndian : ByteOrder::BigEndian; + int i = 1; + auto p = static_cast(static_cast(&i)); + return (*p == 1) ? ByteOrder::LittleEndian : ByteOrder::BigEndian; } } // namespace pag \ No newline at end of file diff --git a/src/codec/utils/ByteOrder.h b/src/codec/utils/ByteOrder.h index a5b8f28776..e814774afb 100644 --- a/src/codec/utils/ByteOrder.h +++ b/src/codec/utils/ByteOrder.h @@ -31,31 +31,31 @@ static const ByteOrder NATIVE_BYTE_ORDER = EndianTest(); static const uint8_t LENGTH_FOR_STORE_NUM_BITS = 5; union Bit8 { - int8_t intValue; - uint8_t uintValue; - bool boolValue; + int8_t intValue; + uint8_t uintValue; + bool boolValue; }; union Bit16 { - uint8_t bytes[2]; - int16_t intValue; - uint16_t uintValue; + uint8_t bytes[2]; + int16_t intValue; + uint16_t uintValue; }; union Bit32 { - uint8_t bytes[4]; - int32_t intValue; - uint32_t uintValue; - float floatValue; + uint8_t bytes[4]; + int32_t intValue; + uint32_t uintValue; + float floatValue; }; union Bit64 { - uint8_t bytes[8]; - int64_t intValue; - uint64_t uintValue; - double doubleValue; + uint8_t bytes[8]; + int64_t intValue; + uint64_t uintValue; + double doubleValue; }; inline uint32_t BitsToBytes(uint64_t capacity) { - return static_cast(ceil(capacity * 0.125)); + return static_cast(ceil(capacity * 0.125)); } } // namespace pag \ No newline at end of file diff --git a/src/codec/utils/DecodeStream.cpp b/src/codec/utils/DecodeStream.cpp index 7d204b6f4d..57d9279b43 100644 --- a/src/codec/utils/DecodeStream.cpp +++ b/src/codec/utils/DecodeStream.cpp @@ -22,255 +22,255 @@ namespace pag { ByteOrder DecodeStream::order() const { - return _order; + return _order; } void DecodeStream::setOrder(pag::ByteOrder order) { - _order = order; + _order = order; } void DecodeStream::setPosition(uint32_t value) { - if (value < _length) { - _position = value; - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } + if (value < _length) { + _position = value; + positionChanged(); + } else { + Throw(context, "End of file was encountered."); + } } void DecodeStream::skip(uint32_t numBytes) { - if (_position < _length - numBytes + 1) { - _position += numBytes; - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } + if (_position < _length - numBytes + 1) { + _position += numBytes; + positionChanged(); + } else { + Throw(context, "End of file was encountered."); + } } DecodeStream DecodeStream::readBytes(uint32_t length) { - if ((_length >= length) && (_position <= _length - length)) { - DecodeStream stream(context, bytes + _position, length); - _position += length; - positionChanged(); - return stream; - } else { - Throw(context, "End of file was encountered."); - } - return DecodeStream(context); + if ((_length >= length) && (_position <= _length - length)) { + DecodeStream stream(context, bytes + _position, length); + _position += length; + positionChanged(); + return stream; + } else { + Throw(context, "End of file was encountered."); + } + return DecodeStream(context); } std::unique_ptr DecodeStream::readByteData() { - auto length = readEncodedUint32(); - auto bytes = readBytes(length); - // must check whether the bytes is valid. otherwise memcpy will crash. - if (length == 0 || context->hasException()) { - return nullptr; - } - return ByteData::MakeCopy(bytes.data(), length); + auto length = readEncodedUint32(); + auto bytes = readBytes(length); + // must check whether the bytes is valid. otherwise memcpy will crash. + if (length == 0 || context->hasException()) { + return nullptr; + } + return ByteData::MakeCopy(bytes.data(), length); } std::string DecodeStream::readUTF8String() { - if (_position < _length) { - auto text = reinterpret_cast(bytes + _position); - auto textLength = strlen(text); - if (textLength > _length - _position) { - textLength = _length - _position; - _position += textLength; + if (_position < _length) { + auto text = reinterpret_cast(bytes + _position); + auto textLength = strlen(text); + if (textLength > _length - _position) { + textLength = _length - _position; + _position += textLength; + } else { + _position += textLength + 1; + } + positionChanged(); + return std::string(text, textLength); } else { - _position += textLength + 1; + Throw(context, "End of file was encountered."); } - positionChanged(); - return std::string(text, textLength); - } else { - Throw(context, "End of file was encountered."); - } - return ""; + return ""; } int32_t DecodeStream::readEncodedInt32() { - auto data = readEncodedUint32(); - int32_t value = data >> 1; - return (data & 1) > 0 ? -value : value; + auto data = readEncodedUint32(); + int32_t value = data >> 1; + return (data & 1) > 0 ? -value : value; } uint32_t DecodeStream::readEncodedUint32() { - static const uint32_t valueMask = 127; - static const uint8_t hasNext = 128; - uint32_t value = 0; - uint32_t byte = 0; - for (int i = 0; i < 32; i += 7) { - if (_position >= _length) { - Throw(context, "End of file was encountered."); - break; - } - byte = bytes[_position++]; - value |= (byte & valueMask) << i; - if ((byte & hasNext) == 0) { - break; + static const uint32_t valueMask = 127; + static const uint8_t hasNext = 128; + uint32_t value = 0; + uint32_t byte = 0; + for (int i = 0; i < 32; i += 7) { + if (_position >= _length) { + Throw(context, "End of file was encountered."); + break; + } + byte = bytes[_position++]; + value |= (byte & valueMask) << i; + if ((byte & hasNext) == 0) { + break; + } } - } - positionChanged(); - return value; + positionChanged(); + return value; } int64_t DecodeStream::readEncodedInt64() { - auto data = readEncodedUint64(); - int64_t value = data >> 1; - return (data & 1) > 0 ? -value : value; + auto data = readEncodedUint64(); + int64_t value = data >> 1; + return (data & 1) > 0 ? -value : value; } uint64_t DecodeStream::readEncodedUint64() { - static const uint64_t valueMask = 127; - static const uint8_t hasNext = 128; - uint64_t value = 0; - uint64_t byte = 0; - for (int i = 0; i < 64; i += 7) { - if (_position >= _length) { - Throw(context, "End of file was encountered."); - break; + static const uint64_t valueMask = 127; + static const uint8_t hasNext = 128; + uint64_t value = 0; + uint64_t byte = 0; + for (int i = 0; i < 64; i += 7) { + if (_position >= _length) { + Throw(context, "End of file was encountered."); + break; + } + byte = bytes[_position++]; + positionChanged(); + value |= (byte & valueMask) << i; + if ((byte & hasNext) == 0) { + break; + } } - byte = bytes[_position++]; - positionChanged(); - value |= (byte & valueMask) << i; - if ((byte & hasNext) == 0) { - break; - } - } - return value; + return value; } int32_t DecodeStream::readBits(uint8_t numBits) { - auto value = readUBits(numBits); - value <<= (32 - numBits); - auto data = static_cast(value); - return data >> (32 - numBits); + auto value = readUBits(numBits); + value <<= (32 - numBits); + auto data = static_cast(value); + return data >> (32 - numBits); } uint32_t DecodeStream::readUBits(uint8_t numBits) { - static const uint8_t bitMasks[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; - uint32_t value = 0; - if ((_length * 8 >= numBits) && (_bitPosition <= static_cast(_length) * 8 - numBits)) { - uint32_t pos = 0; - while (pos < numBits) { - auto bytePosition = static_cast(_bitPosition * 0.125); - auto bitPosition = static_cast(_bitPosition % 8); - auto byte = bytes[bytePosition] >> bitPosition; - auto bitLength = std::min(8 - bitPosition, numBits - pos); - byte &= bitMasks[bitLength]; - value |= static_cast(byte) << pos; - pos += bitLength; - _bitPosition += bitLength; + static const uint8_t bitMasks[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; + uint32_t value = 0; + if ((_length * 8 >= numBits) && (_bitPosition <= static_cast(_length) * 8 - numBits)) { + uint32_t pos = 0; + while (pos < numBits) { + auto bytePosition = static_cast(_bitPosition * 0.125); + auto bitPosition = static_cast(_bitPosition % 8); + auto byte = bytes[bytePosition] >> bitPosition; + auto bitLength = std::min(8 - bitPosition, numBits - pos); + byte &= bitMasks[bitLength]; + value |= static_cast(byte) << pos; + pos += bitLength; + _bitPosition += bitLength; + } + bitPositionChanged(); + } else { + Throw(context, "End of file was encountered."); } - bitPositionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return value; + return value; } void DecodeStream::readInt32List(int32_t* values, uint32_t count) { - auto numBits = readNumBits(); - for (uint32_t i = 0; i < count; i++) { - values[i] = readBits(numBits); - } + auto numBits = readNumBits(); + for (uint32_t i = 0; i < count; i++) { + values[i] = readBits(numBits); + } } void DecodeStream::readUint32List(uint32_t* values, uint32_t count) { - auto numBits = readNumBits(); - for (uint32_t i = 0; i < count; i++) { - values[i] = readUBits(numBits); - } + auto numBits = readNumBits(); + for (uint32_t i = 0; i < count; i++) { + values[i] = readUBits(numBits); + } } void DecodeStream::readFloatList(float* values, uint32_t count, float precision) { - auto numBits = readNumBits(); - for (uint32_t i = 0; i < count; i++) { - values[i] = readBits(numBits) * precision; - } + auto numBits = readNumBits(); + for (uint32_t i = 0; i < count; i++) { + values[i] = readBits(numBits) * precision; + } } Bit8 DecodeStream::readBit8() { - Bit8 data = {}; - if (_position < _length) { - data.uintValue = bytes[_position++]; - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return data; + Bit8 data = {}; + if (_position < _length) { + data.uintValue = bytes[_position++]; + positionChanged(); + } else { + Throw(context, "End of file was encountered."); + } + return data; } Bit16 DecodeStream::readBit16() { - Bit16 data = {}; - if ((_length > 1) && (_position < _length - 1)) { - if (_order == NATIVE_BYTE_ORDER) { - data.bytes[0] = bytes[_position++]; - data.bytes[1] = bytes[_position++]; + Bit16 data = {}; + if ((_length > 1) && (_position < _length - 1)) { + if (_order == NATIVE_BYTE_ORDER) { + data.bytes[0] = bytes[_position++]; + data.bytes[1] = bytes[_position++]; + } else { + data.bytes[1] = bytes[_position++]; + data.bytes[0] = bytes[_position++]; + } + positionChanged(); } else { - data.bytes[1] = bytes[_position++]; - data.bytes[0] = bytes[_position++]; + Throw(context, "End of file was encountered."); } - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return data; + return data; } Bit32 DecodeStream::readBit24() { - Bit32 data = {}; - if ((_length > 2) && (_position < _length - 2)) { - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 3; i++) { - data.bytes[i] = bytes[_position++]; - } + Bit32 data = {}; + if ((_length > 2) && (_position < _length - 2)) { + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 3; i++) { + data.bytes[i] = bytes[_position++]; + } + } else { + for (int i = 3; i >= 1; i--) { + data.bytes[i] = bytes[_position++]; + } + } + positionChanged(); } else { - for (int i = 3; i >= 1; i--) { - data.bytes[i] = bytes[_position++]; - } + Throw(context, "End of file was encountered."); } - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return data; + return data; } Bit32 DecodeStream::readBit32() { - Bit32 data = {}; - if ((_length > 3) && (_position < _length - 3)) { - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 4; i++) { - data.bytes[i] = bytes[_position++]; - } + Bit32 data = {}; + if ((_length > 3) && (_position < _length - 3)) { + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 4; i++) { + data.bytes[i] = bytes[_position++]; + } + } else { + for (int i = 3; i >= 0; i--) { + data.bytes[i] = bytes[_position++]; + } + } + positionChanged(); } else { - for (int i = 3; i >= 0; i--) { - data.bytes[i] = bytes[_position++]; - } + Throw(context, "End of file was encountered."); } - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return data; + return data; } Bit64 DecodeStream::readBit64() { - Bit64 data = {}; - if ((_length > 7) && (_position < _length - 7)) { - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 8; i++) { - data.bytes[i] = bytes[_position++]; - } + Bit64 data = {}; + if ((_length > 7) && (_position < _length - 7)) { + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 8; i++) { + data.bytes[i] = bytes[_position++]; + } + } else { + for (int i = 7; i >= 0; i--) { + data.bytes[i] = bytes[_position++]; + } + } + positionChanged(); } else { - for (int i = 7; i >= 0; i--) { - data.bytes[i] = bytes[_position++]; - } + Throw(context, "End of file was encountered."); } - positionChanged(); - } else { - Throw(context, "End of file was encountered."); - } - return data; + return data; } } // namespace pag diff --git a/src/codec/utils/DecodeStream.h b/src/codec/utils/DecodeStream.h index 7110e9ad46..9a703409e7 100644 --- a/src/codec/utils/DecodeStream.h +++ b/src/codec/utils/DecodeStream.h @@ -32,240 +32,240 @@ namespace pag { * order of DecodeStream is little-endian by default. */ class DecodeStream final { - public: - explicit DecodeStream(StreamContext* context) : context(context) { - } - - DecodeStream(StreamContext* context, const uint8_t* data, uint32_t length) - : context(context), bytes(data), _length(length) { - } - - /** - * This DecodeStream's byte order. The byte order is used when reading or writing multibyte - * values. The order of a newly-created stream is always ByteOrder::LittleEndian. - */ - ByteOrder order() const; - - /** - * Modifies this DecodeStream's byte order. - */ - void setOrder(ByteOrder order); - - /** - * The number of bytes of data available for reading from the current position in the stream to - * the end of the stream. - */ - uint32_t bytesAvailable() const { - return _length - _position; - } - - const uint8_t* data() const { - return bytes; - } - - /** - * The length of the DecodeStream object. - */ - uint32_t length() const { - return _length; - } - - /** - * Moves, or returns the current position, of the file pointer into the DecodeStream object. This - * is the point at which the next call to a read method starts reading. - */ - uint32_t position() const { - return _position; - } - - void setPosition(uint32_t value); - - void skip(uint32_t numBytes); - - void alignWithBytes() { - _bitPosition = static_cast(_position) * 8; - } - - /** - * Reads a Boolean value from the byte stream. A signed 8-bit integer is read, and true is - * returned if the integer is nonzero, false otherwise. - */ - bool readBoolean() { - return readBit8().boolValue; - } - - /** - * Reads a signed 8-bit integer from the byte stream. - */ - int8_t readInt8() { - return readBit8().intValue; - } - - /** - * Reads a unsigned 8-bit integer from the byte stream. - */ - uint8_t readUint8() { - return readBit8().uintValue; - } - - /** - * Reads a signed 16-bit integer from the byte stream. - */ - int16_t readInt16() { - return readBit16().intValue; - } - - /** - * Reads a unsigned 16-bit integer from the byte stream. - */ - uint16_t readUint16() { - return readBit16().uintValue; - } - - /** - * Reads a unsigned 24-bit integer from the byte stream. - */ - uint32_t readUint24() { - return readBit24().uintValue; - } - - /** - * Reads a signed 32-bit integer from the byte stream. - */ - int32_t readInt32() { - return readBit32().intValue; - } - - /** - * Reads a unsigned 32-bit integer from the byte stream. - */ - uint32_t readUint32() { - return readBit32().uintValue; - } - - /** - * Reads a signed 64-bit integer from the byte stream. - */ - int64_t readInt64() { - return readBit64().intValue; - } - - /** - * Reads a unsigned 64-bit integer from the byte stream. - */ - uint64_t readUint64() { - return readBit64().uintValue; - } - - /** - * Reads an IEEE 754 single-precision (32-bit) floating-point number from the byte stream. - */ - float readFloat() { - return readBit32().floatValue; - } - - /** - * Reads an IEEE 754 double-precision (64-bit) floating-point number from the byte stream. - */ - double readDouble() { - return readBit64().doubleValue; - } - - /** - * Reads the number of data bytes, specified by the length parameter, from the byte stream. - * @param length The number of bytes to read. - */ - DecodeStream readBytes(uint32_t length); - - /** - * Reads a ByteData object from the byte stream. - */ - std::unique_ptr readByteData(); - - /** - * Reads a UTF-8 string from the byte stream. The string is assumed to be a sequential list of - * bytes terminated by the null character byte. - */ - std::string readUTF8String(); - - /** - * Reads a encoded signed 32-bit integer from the byte stream. - */ - int32_t readEncodedInt32(); - - /** - * Reads a encoded unsigned 32-bit integer from the byte stream. - */ - uint32_t readEncodedUint32(); - - /** - * Reads a encoded signed 64-bit integer from the byte stream. - */ - int64_t readEncodedInt64(); - - /** - * Reads a encoded unsigned 64-bit integer from the byte stream. - */ - uint64_t readEncodedUint64(); - - /** - * Reads the specified number of bits as an signed integer from the bit stream. - */ - int32_t readBits(uint8_t numBits); - - /** - * Reads the specified number of bits as an unsigned integer from the bit stream. - */ - uint32_t readUBits(uint8_t numBits); - - uint8_t readNumBits() { - return static_cast(readUBits(LENGTH_FOR_STORE_NUM_BITS) + 1); - } - - /** - * Reads a list of int32_t values from the stream. - */ - void readInt32List(int32_t* values, uint32_t count); - - /** - * Reads a list of uint32_t values from the stream. - */ - void readUint32List(uint32_t* values, uint32_t count); - - /** - * Reads a list of float values from the stream. - */ - void readFloatList(float* values, uint32_t count, float precision); - - /** - * Reads a Boolean value from the byte stream. A 1-bit integer is read, and true is returned if - * the integer is nonzero, false otherwise. - */ - bool readBitBoolean() { - return readUBits(1) != 0; - } - - mutable StreamContext* context; - - private: - void bitPositionChanged() { - _position = BitsToBytes(_bitPosition); - } - - void positionChanged() { - _bitPosition = static_cast(_position) * 8; - } - - Bit8 readBit8(); - Bit16 readBit16(); - Bit32 readBit24(); - Bit32 readBit32(); - Bit64 readBit64(); - - ByteOrder _order = ByteOrder::LittleEndian; - const uint8_t* bytes = nullptr; - uint32_t _length = 0; - uint32_t _position = 0; - uint64_t _bitPosition = 0; +public: + explicit DecodeStream(StreamContext* context) : context(context) { + } + + DecodeStream(StreamContext* context, const uint8_t* data, uint32_t length) + : context(context), bytes(data), _length(length) { + } + + /** + * This DecodeStream's byte order. The byte order is used when reading or writing multibyte + * values. The order of a newly-created stream is always ByteOrder::LittleEndian. + */ + ByteOrder order() const; + + /** + * Modifies this DecodeStream's byte order. + */ + void setOrder(ByteOrder order); + + /** + * The number of bytes of data available for reading from the current position in the stream to + * the end of the stream. + */ + uint32_t bytesAvailable() const { + return _length - _position; + } + + const uint8_t* data() const { + return bytes; + } + + /** + * The length of the DecodeStream object. + */ + uint32_t length() const { + return _length; + } + + /** + * Moves, or returns the current position, of the file pointer into the DecodeStream object. This + * is the point at which the next call to a read method starts reading. + */ + uint32_t position() const { + return _position; + } + + void setPosition(uint32_t value); + + void skip(uint32_t numBytes); + + void alignWithBytes() { + _bitPosition = static_cast(_position) * 8; + } + + /** + * Reads a Boolean value from the byte stream. A signed 8-bit integer is read, and true is + * returned if the integer is nonzero, false otherwise. + */ + bool readBoolean() { + return readBit8().boolValue; + } + + /** + * Reads a signed 8-bit integer from the byte stream. + */ + int8_t readInt8() { + return readBit8().intValue; + } + + /** + * Reads a unsigned 8-bit integer from the byte stream. + */ + uint8_t readUint8() { + return readBit8().uintValue; + } + + /** + * Reads a signed 16-bit integer from the byte stream. + */ + int16_t readInt16() { + return readBit16().intValue; + } + + /** + * Reads a unsigned 16-bit integer from the byte stream. + */ + uint16_t readUint16() { + return readBit16().uintValue; + } + + /** + * Reads a unsigned 24-bit integer from the byte stream. + */ + uint32_t readUint24() { + return readBit24().uintValue; + } + + /** + * Reads a signed 32-bit integer from the byte stream. + */ + int32_t readInt32() { + return readBit32().intValue; + } + + /** + * Reads a unsigned 32-bit integer from the byte stream. + */ + uint32_t readUint32() { + return readBit32().uintValue; + } + + /** + * Reads a signed 64-bit integer from the byte stream. + */ + int64_t readInt64() { + return readBit64().intValue; + } + + /** + * Reads a unsigned 64-bit integer from the byte stream. + */ + uint64_t readUint64() { + return readBit64().uintValue; + } + + /** + * Reads an IEEE 754 single-precision (32-bit) floating-point number from the byte stream. + */ + float readFloat() { + return readBit32().floatValue; + } + + /** + * Reads an IEEE 754 double-precision (64-bit) floating-point number from the byte stream. + */ + double readDouble() { + return readBit64().doubleValue; + } + + /** + * Reads the number of data bytes, specified by the length parameter, from the byte stream. + * @param length The number of bytes to read. + */ + DecodeStream readBytes(uint32_t length); + + /** + * Reads a ByteData object from the byte stream. + */ + std::unique_ptr readByteData(); + + /** + * Reads a UTF-8 string from the byte stream. The string is assumed to be a sequential list of + * bytes terminated by the null character byte. + */ + std::string readUTF8String(); + + /** + * Reads a encoded signed 32-bit integer from the byte stream. + */ + int32_t readEncodedInt32(); + + /** + * Reads a encoded unsigned 32-bit integer from the byte stream. + */ + uint32_t readEncodedUint32(); + + /** + * Reads a encoded signed 64-bit integer from the byte stream. + */ + int64_t readEncodedInt64(); + + /** + * Reads a encoded unsigned 64-bit integer from the byte stream. + */ + uint64_t readEncodedUint64(); + + /** + * Reads the specified number of bits as an signed integer from the bit stream. + */ + int32_t readBits(uint8_t numBits); + + /** + * Reads the specified number of bits as an unsigned integer from the bit stream. + */ + uint32_t readUBits(uint8_t numBits); + + uint8_t readNumBits() { + return static_cast(readUBits(LENGTH_FOR_STORE_NUM_BITS) + 1); + } + + /** + * Reads a list of int32_t values from the stream. + */ + void readInt32List(int32_t* values, uint32_t count); + + /** + * Reads a list of uint32_t values from the stream. + */ + void readUint32List(uint32_t* values, uint32_t count); + + /** + * Reads a list of float values from the stream. + */ + void readFloatList(float* values, uint32_t count, float precision); + + /** + * Reads a Boolean value from the byte stream. A 1-bit integer is read, and true is returned if + * the integer is nonzero, false otherwise. + */ + bool readBitBoolean() { + return readUBits(1) != 0; + } + + mutable StreamContext* context; + +private: + void bitPositionChanged() { + _position = BitsToBytes(_bitPosition); + } + + void positionChanged() { + _bitPosition = static_cast(_position) * 8; + } + + Bit8 readBit8(); + Bit16 readBit16(); + Bit32 readBit24(); + Bit32 readBit32(); + Bit64 readBit64(); + + ByteOrder _order = ByteOrder::LittleEndian; + const uint8_t* bytes = nullptr; + uint32_t _length = 0; + uint32_t _position = 0; + uint64_t _bitPosition = 0; }; } // namespace pag diff --git a/src/codec/utils/EncodeStream.cpp b/src/codec/utils/EncodeStream.cpp index 1ad10891db..939b4a21f0 100644 --- a/src/codec/utils/EncodeStream.cpp +++ b/src/codec/utils/EncodeStream.cpp @@ -22,330 +22,330 @@ namespace pag { EncodeStream::EncodeStream(StreamContext* context, uint32_t capacity) : context(context) { - this->capacity = capacity; - bytes = new uint8_t[capacity]; + this->capacity = capacity; + bytes = new uint8_t[capacity]; } EncodeStream::~EncodeStream() { - delete[] bytes; + delete[] bytes; } ByteOrder EncodeStream::order() const { - return _order; + return _order; } void EncodeStream::setOrder(pag::ByteOrder order) { - _order = order; + _order = order; } std::unique_ptr EncodeStream::release() { - auto data = ByteData::MakeAdopted(bytes, _length); - capacity = 256; - _position = 0; - _length = 0; - _bitPosition = 0; - bytes = new uint8_t[capacity]; - return data; + auto data = ByteData::MakeAdopted(bytes, _length); + capacity = 256; + _position = 0; + _length = 0; + _bitPosition = 0; + bytes = new uint8_t[capacity]; + return data; } void EncodeStream::writeBoolean(bool value) { - Bit8 data = {}; - data.boolValue = value; - writeBit8(data); + Bit8 data = {}; + data.boolValue = value; + writeBit8(data); } void EncodeStream::writeInt8(int8_t value) { - Bit8 data = {}; - data.intValue = value; - writeBit8(data); + Bit8 data = {}; + data.intValue = value; + writeBit8(data); } void EncodeStream::writeUint8(uint8_t value) { - Bit8 data = {}; - data.uintValue = value; - writeBit8(data); + Bit8 data = {}; + data.uintValue = value; + writeBit8(data); } void EncodeStream::writeInt16(int16_t value) { - Bit16 data = {}; - data.intValue = value; - writeBit16(data); + Bit16 data = {}; + data.intValue = value; + writeBit16(data); } void EncodeStream::writeUint16(uint16_t value) { - Bit16 data = {}; - data.uintValue = value; - writeBit16(data); + Bit16 data = {}; + data.uintValue = value; + writeBit16(data); } void EncodeStream::writeUint24(uint32_t value) { - Bit32 data = {}; - data.uintValue = value; - writeBit24(data); + Bit32 data = {}; + data.uintValue = value; + writeBit24(data); } void EncodeStream::writeInt32(int32_t value) { - Bit32 data = {}; - data.intValue = value; - writeBit32(data); + Bit32 data = {}; + data.intValue = value; + writeBit32(data); } void EncodeStream::writeUint32(uint32_t value) { - Bit32 data = {}; - data.uintValue = value; - writeBit32(data); + Bit32 data = {}; + data.uintValue = value; + writeBit32(data); } void EncodeStream::writeInt64(int64_t value) { - Bit64 data = {}; - data.intValue = value; - writeBit64(data); + Bit64 data = {}; + data.intValue = value; + writeBit64(data); } void EncodeStream::writeUint64(uint64_t value) { - Bit64 data = {}; - data.uintValue = value; - writeBit64(data); + Bit64 data = {}; + data.uintValue = value; + writeBit64(data); } void EncodeStream::writeFloat(float value) { - Bit32 data = {}; - data.floatValue = value; - writeBit32(data); + Bit32 data = {}; + data.floatValue = value; + writeBit32(data); } void EncodeStream::writeDouble(double value) { - Bit64 data = {}; - data.doubleValue = value; - writeBit64(data); + Bit64 data = {}; + data.doubleValue = value; + writeBit64(data); } void EncodeStream::writeBytes(EncodeStream* stream, uint32_t length, uint32_t offset) { - if (stream->_length <= offset) { - return; - } - if (length == 0) { - length = stream->_length - offset; - } - writeBytes(stream->bytes, length, offset); + if (stream->_length <= offset) { + return; + } + if (length == 0) { + length = stream->_length - offset; + } + writeBytes(stream->bytes, length, offset); } void EncodeStream::writeBytes(uint8_t* stream, uint32_t length, uint32_t offset) { - ensureCapacity(_position + length); - memcpy(bytes + _position, stream + offset, length); - _position += length; - positionChanged(); + ensureCapacity(_position + length); + memcpy(bytes + _position, stream + offset, length); + _position += length; + positionChanged(); } void EncodeStream::writeByteData(const pag::ByteData* byteData) { - if (byteData == nullptr) { - return; - } - auto length = static_cast(byteData->length()); - writeEncodedUint32(length); - writeBytes(byteData->data(), length); + if (byteData == nullptr) { + return; + } + auto length = static_cast(byteData->length()); + writeEncodedUint32(length); + writeBytes(byteData->data(), length); } void EncodeStream::writeUTF8String(const std::string& text) { - auto textLength = text.size(); - ensureCapacity(static_cast(_position + textLength + 1)); - memcpy(bytes + _position, text.c_str(), textLength + 1); - _position += textLength + 1; - positionChanged(); + auto textLength = text.size(); + ensureCapacity(static_cast(_position + textLength + 1)); + memcpy(bytes + _position, text.c_str(), textLength + 1); + _position += textLength + 1; + positionChanged(); } void EncodeStream::writeEncodedInt64(int64_t value) { - uint64_t flag = value < 0 ? 1 : 0; - auto data = static_cast(value < 0 ? -value : value); - data = (data << 1) | flag; - writeEncodedUint64(data); + uint64_t flag = value < 0 ? 1 : 0; + auto data = static_cast(value < 0 ? -value : value); + data = (data << 1) | flag; + writeEncodedUint64(data); } void EncodeStream::writeEncodedUint64(uint64_t value) { - static const uint64_t valueMask = 127; - static const uint8_t hasNext = 128; - uint8_t byte = 0; - for (int i = 0; i < 64; i += 7) { - byte = static_cast(value & valueMask); - value >>= 7; - if (value > 0) { - byte |= hasNext; - } - ensureCapacity(_position + 1); - bytes[_position++] = byte; - positionChanged(); - if (value == 0) { - break; + static const uint64_t valueMask = 127; + static const uint8_t hasNext = 128; + uint8_t byte = 0; + for (int i = 0; i < 64; i += 7) { + byte = static_cast(value & valueMask); + value >>= 7; + if (value > 0) { + byte |= hasNext; + } + ensureCapacity(_position + 1); + bytes[_position++] = byte; + positionChanged(); + if (value == 0) { + break; + } } - } } void EncodeStream::writeBits(int32_t value, uint8_t numBits) { - auto data = static_cast(value << (33 - numBits)); - data >>= 33 - numBits; - if (value < 0) { - data |= 1 << (numBits - 1); - } - writeUBits(data, numBits); + auto data = static_cast(value << (33 - numBits)); + data >>= 33 - numBits; + if (value < 0) { + data |= 1 << (numBits - 1); + } + writeUBits(data, numBits); } void EncodeStream::writeUBits(uint32_t value, uint8_t numBits) { - static const uint8_t bitMasks[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; - ensureCapacity(BitsToBytes(_bitPosition + numBits)); - while (numBits > 0) { - auto bytePosition = static_cast(_bitPosition * 0.125); - auto bitPosition = static_cast(_bitPosition % 8); - auto& byte = bytes[bytePosition]; - byte &= bitMasks[bitPosition]; - auto bitLength = std::min(8 - bitPosition, static_cast(numBits)); - auto bits = static_cast(value) & bitMasks[bitLength]; - byte |= (bits << bitPosition); - value >>= bitLength; - numBits -= bitLength; - _bitPosition += bitLength; - } - bitPositionChanged(); + static const uint8_t bitMasks[9] = {0, 1, 3, 7, 15, 31, 63, 127, 255}; + ensureCapacity(BitsToBytes(_bitPosition + numBits)); + while (numBits > 0) { + auto bytePosition = static_cast(_bitPosition * 0.125); + auto bitPosition = static_cast(_bitPosition % 8); + auto& byte = bytes[bytePosition]; + byte &= bitMasks[bitPosition]; + auto bitLength = std::min(8 - bitPosition, static_cast(numBits)); + auto bits = static_cast(value) & bitMasks[bitLength]; + byte |= (bits << bitPosition); + value >>= bitLength; + numBits -= bitLength; + _bitPosition += bitLength; + } + bitPositionChanged(); } uint8_t GetBitLength(uint32_t data) { - uint8_t length = 32; - static const uint32_t mask = 1ull << 31; - while (length > 1) { - if ((data & mask) > 0) { - break; + uint8_t length = 32; + static const uint32_t mask = 1ull << 31; + while (length > 1) { + if ((data & mask) > 0) { + break; + } + data <<= 1; + length--; } - data <<= 1; - length--; - } - return static_cast(length); + return static_cast(length); } uint8_t GetBitLength(int32_t value) { - auto data = static_cast(value < 0 ? -value : value); - uint8_t length = GetBitLength(data); - if (length >= 32) { - length = 31; - } - return static_cast(length + 1); + auto data = static_cast(value < 0 ? -value : value); + uint8_t length = GetBitLength(data); + if (length >= 32) { + length = 31; + } + return static_cast(length + 1); } void EncodeStream::writeInt32List(const int32_t* values, uint32_t count) { - if (count == 0) { - writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); - return; - } - uint8_t bitLength = 1; - for (uint32_t i = 0; i < count; i++) { - auto length = GetBitLength(values[i]); - if (bitLength < length) { - bitLength = length; + if (count == 0) { + writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); + return; + } + uint8_t bitLength = 1; + for (uint32_t i = 0; i < count; i++) { + auto length = GetBitLength(values[i]); + if (bitLength < length) { + bitLength = length; + } + } + writeUBits(static_cast(bitLength - 1), LENGTH_FOR_STORE_NUM_BITS); + for (uint32_t i = 0; i < count; i++) { + writeBits(values[i], bitLength); } - } - writeUBits(static_cast(bitLength - 1), LENGTH_FOR_STORE_NUM_BITS); - for (uint32_t i = 0; i < count; i++) { - writeBits(values[i], bitLength); - } } void EncodeStream::writeUint32List(const uint32_t* values, uint32_t count) { - if (count == 0) { - writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); - return; - } - uint8_t bitLength = 1; - for (uint32_t i = 0; i < count; i++) { - auto length = GetBitLength(values[i]); - if (bitLength < length) { - bitLength = length; + if (count == 0) { + writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); + return; + } + uint8_t bitLength = 1; + for (uint32_t i = 0; i < count; i++) { + auto length = GetBitLength(values[i]); + if (bitLength < length) { + bitLength = length; + } + } + writeUBits(static_cast(bitLength - 1), LENGTH_FOR_STORE_NUM_BITS); + for (uint32_t i = 0; i < count; i++) { + writeUBits(values[i], bitLength); } - } - writeUBits(static_cast(bitLength - 1), LENGTH_FOR_STORE_NUM_BITS); - for (uint32_t i = 0; i < count; i++) { - writeUBits(values[i], bitLength); - } } void EncodeStream::writeFloatList(const float* values, uint32_t count, float precision) { - if (count == 0) { - writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); - return; - } - auto scale = 1 / precision; - auto list = new int32_t[count]; - for (uint32_t i = 0; i < count; i++) { - list[i] = static_cast(roundf(values[i] * scale)); - } - writeInt32List(list, count); - delete[] list; + if (count == 0) { + writeUBits(0, LENGTH_FOR_STORE_NUM_BITS); + return; + } + auto scale = 1 / precision; + auto list = new int32_t[count]; + for (uint32_t i = 0; i < count; i++) { + list[i] = static_cast(roundf(values[i] * scale)); + } + writeInt32List(list, count); + delete[] list; } void EncodeStream::expandCapacity(uint32_t length) { - while (capacity < length) { - capacity = static_cast(capacity * 1.5); - } - auto newBytes = new uint8_t[capacity]; - memcpy(newBytes, bytes, _length); - delete[] bytes; - bytes = newBytes; + while (capacity < length) { + capacity = static_cast(capacity * 1.5); + } + auto newBytes = new uint8_t[capacity]; + memcpy(newBytes, bytes, _length); + delete[] bytes; + bytes = newBytes; } void EncodeStream::writeBit8(Bit8 data) { - ensureCapacity(_position + 1); - bytes[_position++] = data.uintValue; - positionChanged(); + ensureCapacity(_position + 1); + bytes[_position++] = data.uintValue; + positionChanged(); } void EncodeStream::writeBit16(Bit16 data) { - ensureCapacity(_position + 2); - if (_order == NATIVE_BYTE_ORDER) { - bytes[_position++] = data.bytes[0]; - bytes[_position++] = data.bytes[1]; - } else { - bytes[_position++] = data.bytes[1]; - bytes[_position++] = data.bytes[0]; - } - positionChanged(); + ensureCapacity(_position + 2); + if (_order == NATIVE_BYTE_ORDER) { + bytes[_position++] = data.bytes[0]; + bytes[_position++] = data.bytes[1]; + } else { + bytes[_position++] = data.bytes[1]; + bytes[_position++] = data.bytes[0]; + } + positionChanged(); } void EncodeStream::writeBit24(Bit32 data) { - ensureCapacity(_position + 3); - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 3; i++) { - bytes[_position++] = data.bytes[i]; - } - } else { - for (int i = 3; i >= 1; i--) { - bytes[_position++] = data.bytes[i]; + ensureCapacity(_position + 3); + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 3; i++) { + bytes[_position++] = data.bytes[i]; + } + } else { + for (int i = 3; i >= 1; i--) { + bytes[_position++] = data.bytes[i]; + } } - } - positionChanged(); + positionChanged(); } void EncodeStream::writeBit32(Bit32 data) { - ensureCapacity(_position + 4); - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 4; i++) { - bytes[_position++] = data.bytes[i]; - } - } else { - for (int i = 3; i >= 0; i--) { - bytes[_position++] = data.bytes[i]; + ensureCapacity(_position + 4); + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 4; i++) { + bytes[_position++] = data.bytes[i]; + } + } else { + for (int i = 3; i >= 0; i--) { + bytes[_position++] = data.bytes[i]; + } } - } - positionChanged(); + positionChanged(); } void EncodeStream::writeBit64(Bit64 data) { - ensureCapacity(_position + 8); - if (_order == NATIVE_BYTE_ORDER) { - for (int i = 0; i < 8; i++) { - bytes[_position++] = data.bytes[i]; - } - } else { - for (int i = 7; i >= 0; i--) { - bytes[_position++] = data.bytes[i]; + ensureCapacity(_position + 8); + if (_order == NATIVE_BYTE_ORDER) { + for (int i = 0; i < 8; i++) { + bytes[_position++] = data.bytes[i]; + } + } else { + for (int i = 7; i >= 0; i--) { + bytes[_position++] = data.bytes[i]; + } } - } - positionChanged(); + positionChanged(); } } // namespace pag diff --git a/src/codec/utils/EncodeStream.h b/src/codec/utils/EncodeStream.h index a2dfe4ab1f..817ebd5087 100644 --- a/src/codec/utils/EncodeStream.h +++ b/src/codec/utils/EncodeStream.h @@ -29,231 +29,231 @@ namespace pag { * binary data. Note: The byte order of EncodeStream is always little-endian. */ class EncodeStream final { - public: - explicit EncodeStream(StreamContext* context, uint32_t capacity = 128); - - ~EncodeStream(); - - /** - * This EncodeStream's byte order. The byte order is used when reading or writing multibyte - * values. The order of a newly-created stream is always ByteOrder::LittleEndian. - */ - ByteOrder order() const; - - /** - * Modifies this EncodeStream's byte order. - */ - void setOrder(ByteOrder order); - - /** - * Call the this method to take ownership of the current bytes. Once the release method is called, - * the EncodeStream object will be reset to a new one, and the returned bytes will be managed by - * the ByteData object. - */ - std::unique_ptr release(); - - /** - * The length of the EncodeStream object. - */ - uint32_t length() const { - return _length; - } - - /** - * Moves, or returns the current position, of the file pointer into the EncodeStream object. This - * is the point at which the next call to a write method starts writing. - */ - uint32_t position() const { - return _position; - } - - void setPosition(uint32_t value) { - _position = value; - positionChanged(); - } - - void alignWithBytes() { - _bitPosition = static_cast(_position) * 8; - } - - /** - * Writes a Boolean value. A signed 8-bit integer is written according to the value parameter, - * either 1 if true or 0 if false. - */ - void writeBoolean(bool value); - - /** - * Writes a 8-bit signed integer to the byte stream. - */ - void writeInt8(int8_t value); - - /** - * Writes a unsigned 8-bit integer to the byte stream. - */ - void writeUint8(uint8_t value); - - /** - * Writes a 16-bit signed integer to the byte stream. - */ - void writeInt16(int16_t value); - - /** - * Writes a unsigned 16-bit integer to the byte stream. - */ - void writeUint16(uint16_t value); - - /** - * Writes a unsigned 24-bit integer to the byte stream. - */ - void writeUint24(uint32_t value); - - /** - * Writes a 32-bit signed integer to the byte stream. - */ - void writeInt32(int32_t value); - - /** - * Writes a unsigned 32-bit integer to the byte stream. - */ - void writeUint32(uint32_t value); - - /** - * Writes a 64-bit signed integer to the byte stream. - */ - void writeInt64(int64_t value); - - /** - * Writes a unsigned 64-bit integer to the byte stream. - */ - void writeUint64(uint64_t value); - - /** - * Writes an IEEE 754 single-precision (32-bit) floating-point number to the byte stream. - */ - void writeFloat(float value); - - /** - * Writes an IEEE 754 double-precision (64-bit) floating-point number to the byte stream. - */ - void writeDouble(double value); - - /** - * Writes a sequence of length bytes from the specified stream, bytes, starting - * offset(zero-based index) bytes into the byte stream. If the length parameter is omitted, the - * default length of 0 is used; the method writes the entire stream starting at offset. If the - * offset parameter is also omitted, the entire stream is written. If offset or length is out of - * range, they are clamped to the beginning and end of the stream. Note: The position of target - * EncodeStream will not change. - * @param stream The EncodeStream object. - * @param offset A zero-based index indicating the position into the stream to begin writing. - * @param length An unsigned integer indicating how far into the stream to write. - */ - void writeBytes(EncodeStream* stream, uint32_t length = 0, uint32_t offset = 0); - - void writeBytes(uint8_t* stream, uint32_t length, uint32_t offset = 0); - - /** - * Writes a ByteData object to the byte stream. - */ - void writeByteData(const ByteData* byteData); - - /** - * Writes a UTF-8 string to the byte stream. The bytes representing the characters of the string - * are written first, followed by the null character byte. - */ - void writeUTF8String(const std::string& text); - - /** - * Writes a encoded signed 32-bit integer to the byte stream. - */ - void writeEncodedInt32(int32_t value) { - writeEncodedInt64(value); - } - - /** - * Writes a encoded unsigned 32-bit integer to the byte stream. - */ - void writeEncodedUint32(uint32_t value) { - writeEncodedUint64(value); - } - - /** - * Writes a encoded signed 64-bit integer to the byte stream. - */ - void writeEncodedInt64(int64_t value); - - /** - * Writes a encoded unsigned 64-bit integer to the byte stream. - */ - void writeEncodedUint64(uint64_t value); - - /** - * Writes the signed bit and numBits-1 of a signed integer's lower bits to the bit stream. - */ - void writeBits(int32_t value, uint8_t numBits); - /** - * Writes the specified number of a unsigned integer's lower bits to the bit stream. - */ - void writeUBits(uint32_t value, uint8_t numBits); - - /** - * Writes a list of int32_t values to the stream. - */ - void writeInt32List(const int32_t* values, uint32_t count); - - /** - * Writes a list of uint32_t values to the stream. - */ - void writeUint32List(const uint32_t* values, uint32_t count); - - /** - * Writes a list of float values to the stream. - */ - void writeFloatList(const float* values, uint32_t count, float precision); - - /** - * Writes a Boolean value. A 1-bit integer is written according to the value parameter, either 1 - * if true or 0 if false. - */ - void writeBitBoolean(bool value) { - writeUBits(value ? 1 : 0, 1); - } - - mutable StreamContext* context; - - private: - void ensureCapacity(uint32_t length) { - if (length > capacity) { - expandCapacity(length); +public: + explicit EncodeStream(StreamContext* context, uint32_t capacity = 128); + + ~EncodeStream(); + + /** + * This EncodeStream's byte order. The byte order is used when reading or writing multibyte + * values. The order of a newly-created stream is always ByteOrder::LittleEndian. + */ + ByteOrder order() const; + + /** + * Modifies this EncodeStream's byte order. + */ + void setOrder(ByteOrder order); + + /** + * Call the this method to take ownership of the current bytes. Once the release method is called, + * the EncodeStream object will be reset to a new one, and the returned bytes will be managed by + * the ByteData object. + */ + std::unique_ptr release(); + + /** + * The length of the EncodeStream object. + */ + uint32_t length() const { + return _length; } - } - void bitPositionChanged() { - _position = BitsToBytes(_bitPosition); - if (_position > _length) { - _length = _position; + /** + * Moves, or returns the current position, of the file pointer into the EncodeStream object. This + * is the point at which the next call to a write method starts writing. + */ + uint32_t position() const { + return _position; } - } - void positionChanged() { - _bitPosition = static_cast(_position) * 8; - if (_position > _length) { - _length = _position; + void setPosition(uint32_t value) { + _position = value; + positionChanged(); } - } - - void expandCapacity(uint32_t length); - void writeBit8(Bit8 data); - void writeBit16(Bit16 data); - void writeBit24(Bit32 data); - void writeBit32(Bit32 data); - void writeBit64(Bit64 data); - - ByteOrder _order = ByteOrder::LittleEndian; - uint8_t* bytes = nullptr; - uint32_t capacity = 0; - uint32_t _length = 0; - uint32_t _position = 0; - uint64_t _bitPosition = 0; + + void alignWithBytes() { + _bitPosition = static_cast(_position) * 8; + } + + /** + * Writes a Boolean value. A signed 8-bit integer is written according to the value parameter, + * either 1 if true or 0 if false. + */ + void writeBoolean(bool value); + + /** + * Writes a 8-bit signed integer to the byte stream. + */ + void writeInt8(int8_t value); + + /** + * Writes a unsigned 8-bit integer to the byte stream. + */ + void writeUint8(uint8_t value); + + /** + * Writes a 16-bit signed integer to the byte stream. + */ + void writeInt16(int16_t value); + + /** + * Writes a unsigned 16-bit integer to the byte stream. + */ + void writeUint16(uint16_t value); + + /** + * Writes a unsigned 24-bit integer to the byte stream. + */ + void writeUint24(uint32_t value); + + /** + * Writes a 32-bit signed integer to the byte stream. + */ + void writeInt32(int32_t value); + + /** + * Writes a unsigned 32-bit integer to the byte stream. + */ + void writeUint32(uint32_t value); + + /** + * Writes a 64-bit signed integer to the byte stream. + */ + void writeInt64(int64_t value); + + /** + * Writes a unsigned 64-bit integer to the byte stream. + */ + void writeUint64(uint64_t value); + + /** + * Writes an IEEE 754 single-precision (32-bit) floating-point number to the byte stream. + */ + void writeFloat(float value); + + /** + * Writes an IEEE 754 double-precision (64-bit) floating-point number to the byte stream. + */ + void writeDouble(double value); + + /** + * Writes a sequence of length bytes from the specified stream, bytes, starting + * offset(zero-based index) bytes into the byte stream. If the length parameter is omitted, the + * default length of 0 is used; the method writes the entire stream starting at offset. If the + * offset parameter is also omitted, the entire stream is written. If offset or length is out of + * range, they are clamped to the beginning and end of the stream. Note: The position of target + * EncodeStream will not change. + * @param stream The EncodeStream object. + * @param offset A zero-based index indicating the position into the stream to begin writing. + * @param length An unsigned integer indicating how far into the stream to write. + */ + void writeBytes(EncodeStream* stream, uint32_t length = 0, uint32_t offset = 0); + + void writeBytes(uint8_t* stream, uint32_t length, uint32_t offset = 0); + + /** + * Writes a ByteData object to the byte stream. + */ + void writeByteData(const ByteData* byteData); + + /** + * Writes a UTF-8 string to the byte stream. The bytes representing the characters of the string + * are written first, followed by the null character byte. + */ + void writeUTF8String(const std::string& text); + + /** + * Writes a encoded signed 32-bit integer to the byte stream. + */ + void writeEncodedInt32(int32_t value) { + writeEncodedInt64(value); + } + + /** + * Writes a encoded unsigned 32-bit integer to the byte stream. + */ + void writeEncodedUint32(uint32_t value) { + writeEncodedUint64(value); + } + + /** + * Writes a encoded signed 64-bit integer to the byte stream. + */ + void writeEncodedInt64(int64_t value); + + /** + * Writes a encoded unsigned 64-bit integer to the byte stream. + */ + void writeEncodedUint64(uint64_t value); + + /** + * Writes the signed bit and numBits-1 of a signed integer's lower bits to the bit stream. + */ + void writeBits(int32_t value, uint8_t numBits); + /** + * Writes the specified number of a unsigned integer's lower bits to the bit stream. + */ + void writeUBits(uint32_t value, uint8_t numBits); + + /** + * Writes a list of int32_t values to the stream. + */ + void writeInt32List(const int32_t* values, uint32_t count); + + /** + * Writes a list of uint32_t values to the stream. + */ + void writeUint32List(const uint32_t* values, uint32_t count); + + /** + * Writes a list of float values to the stream. + */ + void writeFloatList(const float* values, uint32_t count, float precision); + + /** + * Writes a Boolean value. A 1-bit integer is written according to the value parameter, either 1 + * if true or 0 if false. + */ + void writeBitBoolean(bool value) { + writeUBits(value ? 1 : 0, 1); + } + + mutable StreamContext* context; + +private: + void ensureCapacity(uint32_t length) { + if (length > capacity) { + expandCapacity(length); + } + } + + void bitPositionChanged() { + _position = BitsToBytes(_bitPosition); + if (_position > _length) { + _length = _position; + } + } + + void positionChanged() { + _bitPosition = static_cast(_position) * 8; + if (_position > _length) { + _length = _position; + } + } + + void expandCapacity(uint32_t length); + void writeBit8(Bit8 data); + void writeBit16(Bit16 data); + void writeBit24(Bit32 data); + void writeBit32(Bit32 data); + void writeBit64(Bit64 data); + + ByteOrder _order = ByteOrder::LittleEndian; + uint8_t* bytes = nullptr; + uint32_t capacity = 0; + uint32_t _length = 0; + uint32_t _position = 0; + uint64_t _bitPosition = 0; }; } // namespace pag diff --git a/src/codec/utils/NALUReader.cpp b/src/codec/utils/NALUReader.cpp index 939f50041f..16ae6dcc49 100644 --- a/src/codec/utils/NALUReader.cpp +++ b/src/codec/utils/NALUReader.cpp @@ -21,27 +21,27 @@ namespace pag { std::unique_ptr ReadByteDataWithStartCode(DecodeStream* stream) { - auto length = stream->readEncodedUint32(); - auto bytes = stream->readBytes(length); - // must check whether the bytes is valid. otherwise memcpy will crash. - if (length == 0 || stream->context->hasException()) { - return nullptr; - } - auto data = new uint8_t[length + 4]; - memcpy(data + 4, bytes.data(), length); - if (Platform::Current()->naluType() == NALUType::AVCC) { - // AVCC - data[0] = static_cast((length >> 24) & 0xFF); - data[1] = static_cast((length >> 16) & 0x00FF); - data[2] = static_cast((length >> 8) & 0x0000FF); - data[3] = static_cast(length & 0x000000FF); - } else { - // Annex B Prefix - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 1; - } - return ByteData::MakeAdopted(data, length + 4); + auto length = stream->readEncodedUint32(); + auto bytes = stream->readBytes(length); + // must check whether the bytes is valid. otherwise memcpy will crash. + if (length == 0 || stream->context->hasException()) { + return nullptr; + } + auto data = new uint8_t[length + 4]; + memcpy(data + 4, bytes.data(), length); + if (Platform::Current()->naluType() == NALUType::AVCC) { + // AVCC + data[0] = static_cast((length >> 24) & 0xFF); + data[1] = static_cast((length >> 16) & 0x00FF); + data[2] = static_cast((length >> 8) & 0x0000FF); + data[3] = static_cast(length & 0x000000FF); + } else { + // Annex B Prefix + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 1; + } + return ByteData::MakeAdopted(data, length + 4); } } // namespace pag diff --git a/src/codec/utils/StreamContext.h b/src/codec/utils/StreamContext.h index e7faeae7c3..1bda551de3 100644 --- a/src/codec/utils/StreamContext.h +++ b/src/codec/utils/StreamContext.h @@ -24,18 +24,18 @@ namespace pag { class StreamContext { - public: - virtual ~StreamContext() = default; +public: + virtual ~StreamContext() = default; - void throwException(const std::string& message) { - errorMessages.push_back(message); - } + void throwException(const std::string& message) { + errorMessages.push_back(message); + } - bool hasException() { - return !errorMessages.empty(); - } + bool hasException() { + return !errorMessages.empty(); + } - std::vector errorMessages; + std::vector errorMessages; }; #ifdef DEBUG diff --git a/src/codec/utils/WebpDecoder.cpp b/src/codec/utils/WebpDecoder.cpp index cf3f823bc9..51e2796891 100644 --- a/src/codec/utils/WebpDecoder.cpp +++ b/src/codec/utils/WebpDecoder.cpp @@ -24,90 +24,90 @@ namespace pag { // Read 16, 24 or 32 bits stored in little-endian order. static WEBP_INLINE int GetLE16(const uint8_t* const data) { - return (int)(data[0] << 0) | (data[1] << 8); + return (int)(data[0] << 0) | (data[1] << 8); } static WEBP_INLINE int GetLE24(const uint8_t* const data) { - return GetLE16(data) | (data[2] << 16); + return GetLE16(data) | (data[2] << 16); } static WEBP_INLINE uint32_t GetLE32(const uint8_t* const data) { - return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); + return GetLE16(data) | ((uint32_t)GetLE16(data + 2) << 16); } static VP8StatusCode ParseVP8X(const uint8_t** const data, size_t* const data_size, int* const found_vp8x, int* const width_ptr, int* const height_ptr, uint32_t* const flags_ptr) { - const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; - assert(data != nullptr); - assert(data_size != nullptr); - assert(found_vp8x != nullptr); - - *found_vp8x = 0; - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (!memcmp(*data, "VP8X", TAG_SIZE)) { - int width, height; - uint32_t flags; - const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); - if (chunk_size != VP8X_CHUNK_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. - } + const uint32_t vp8x_size = CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE; + assert(data != nullptr); + assert(data_size != nullptr); + assert(found_vp8x != nullptr); - // Verify if enough data is available to validate the VP8X chunk. - if (*data_size < vp8x_size) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - flags = GetLE32(*data + 8); - width = 1 + GetLE24(*data + 12); - height = 1 + GetLE24(*data + 15); - if (width * (uint64_t)height >= MAX_IMAGE_AREA) { - return VP8_STATUS_BITSTREAM_ERROR; // image is too large + *found_vp8x = 0; + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. } - if (flags_ptr != nullptr) *flags_ptr = flags; - if (width_ptr != nullptr) *width_ptr = width; - if (height_ptr != nullptr) *height_ptr = height; - // Skip over VP8X header bytes. - *data += vp8x_size; - *data_size -= vp8x_size; - *found_vp8x = 1; - } - return VP8_STATUS_OK; + if (!memcmp(*data, "VP8X", TAG_SIZE)) { + int width, height; + uint32_t flags; + const uint32_t chunk_size = GetLE32(*data + TAG_SIZE); + if (chunk_size != VP8X_CHUNK_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong chunk size. + } + + // Verify if enough data is available to validate the VP8X chunk. + if (*data_size < vp8x_size) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. + } + flags = GetLE32(*data + 8); + width = 1 + GetLE24(*data + 12); + height = 1 + GetLE24(*data + 15); + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return VP8_STATUS_BITSTREAM_ERROR; // image is too large + } + + if (flags_ptr != nullptr) *flags_ptr = flags; + if (width_ptr != nullptr) *width_ptr = width; + if (height_ptr != nullptr) *height_ptr = height; + // Skip over VP8X header bytes. + *data += vp8x_size; + *data_size -= vp8x_size; + *found_vp8x = 1; + } + return VP8_STATUS_OK; } static VP8StatusCode ParseRIFF(const uint8_t** const data, size_t* const data_size, int have_all_data, size_t* const riff_size) { - assert(data != nullptr); - assert(data_size != nullptr); - assert(riff_size != nullptr); - - *riff_size = 0; // Default: no RIFF present. - if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { - if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { - return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. - } else { - const uint32_t size = GetLE32(*data + TAG_SIZE); - // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). - if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. - } - // We have a RIFF container. Skip it. - *riff_size = size; - *data += RIFF_HEADER_SIZE; - *data_size -= RIFF_HEADER_SIZE; + assert(data != nullptr); + assert(data_size != nullptr); + assert(riff_size != nullptr); + + *riff_size = 0; // Default: no RIFF present. + if (*data_size >= RIFF_HEADER_SIZE && !memcmp(*data, "RIFF", TAG_SIZE)) { + if (memcmp(*data + 8, "WEBP", TAG_SIZE)) { + return VP8_STATUS_BITSTREAM_ERROR; // Wrong image file signature. + } else { + const uint32_t size = GetLE32(*data + TAG_SIZE); + // Check that we have at least one chunk (i.e "WEBP" + "VP8?nnnn"). + if (size < TAG_SIZE + CHUNK_HEADER_SIZE) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // We have a RIFF container. Skip it. + *riff_size = size; + *data += RIFF_HEADER_SIZE; + *data_size -= RIFF_HEADER_SIZE; + } } - } - return VP8_STATUS_OK; + return VP8_STATUS_OK; } // Skips to the next VP8/VP8L chunk header in the data given the size of the @@ -118,73 +118,73 @@ static VP8StatusCode ParseRIFF(const uint8_t** const data, size_t* const data_si // If an alpha chunk is found, *alpha_data and *alpha_size are set // appropriately. static VP8StatusCode ParseOptionalChunks(const uint8_t** const data, size_t* const data_size, - size_t const riff_size, const uint8_t** const alpha_data, - size_t* const alpha_size) { - const uint8_t* buf; - size_t buf_size; - uint32_t total_size = TAG_SIZE + // "WEBP". - CHUNK_HEADER_SIZE + // "VP8Xnnnn". - VP8X_CHUNK_SIZE; // data. - assert(data != nullptr); - assert(data_size != nullptr); - buf = *data; - buf_size = *data_size; - - assert(alpha_data != nullptr); - assert(alpha_size != nullptr); - *alpha_data = nullptr; - *alpha_size = 0; - - while (1) { - uint32_t chunk_size; - uint32_t disk_chunk_size; // chunk_size with padding - - *data = buf; - *data_size = buf_size; - - if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - chunk_size = GetLE32(buf + TAG_SIZE); - if (chunk_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - // For odd-sized chunk-payload, there's one byte padding at the end. - disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; - total_size += disk_chunk_size; - - // Check that total bytes skipped so far does not exceed riff_size. - if (riff_size > 0 && (total_size > riff_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. - } - - // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have - // parsed all the optional chunks. - // Note: This check must occur before the check 'buf_size < disk_chunk_size' - // below to allow incomplete VP8/VP8L chunks. - if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) { - return VP8_STATUS_OK; + size_t const riff_size, const uint8_t** const alpha_data, + size_t* const alpha_size) { + const uint8_t* buf; + size_t buf_size; + uint32_t total_size = TAG_SIZE + // "WEBP". + CHUNK_HEADER_SIZE + // "VP8Xnnnn". + VP8X_CHUNK_SIZE; // data. + assert(data != nullptr); + assert(data_size != nullptr); + buf = *data; + buf_size = *data_size; + + assert(alpha_data != nullptr); + assert(alpha_size != nullptr); + *alpha_data = nullptr; + *alpha_size = 0; + + while (1) { + uint32_t chunk_size; + uint32_t disk_chunk_size; // chunk_size with padding + + *data = buf; + *data_size = buf_size; + + if (buf_size < CHUNK_HEADER_SIZE) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + chunk_size = GetLE32(buf + TAG_SIZE); + if (chunk_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + // For odd-sized chunk-payload, there's one byte padding at the end. + disk_chunk_size = (CHUNK_HEADER_SIZE + chunk_size + 1) & ~1; + total_size += disk_chunk_size; + + // Check that total bytes skipped so far does not exceed riff_size. + if (riff_size > 0 && (total_size > riff_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Not a valid chunk size. + } + + // Start of a (possibly incomplete) VP8/VP8L chunk implies that we have + // parsed all the optional chunks. + // Note: This check must occur before the check 'buf_size < disk_chunk_size' + // below to allow incomplete VP8/VP8L chunks. + if (!memcmp(buf, "VP8 ", TAG_SIZE) || !memcmp(buf, "VP8L", TAG_SIZE)) { + return VP8_STATUS_OK; + } + + if (buf_size < disk_chunk_size) { // Insufficient data. + return VP8_STATUS_NOT_ENOUGH_DATA; + } + + if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. + *alpha_data = buf + CHUNK_HEADER_SIZE; + *alpha_size = chunk_size; + } + + // We have a full and valid chunk; skip it. + buf += disk_chunk_size; + buf_size -= disk_chunk_size; } - - if (buf_size < disk_chunk_size) { // Insufficient data. - return VP8_STATUS_NOT_ENOUGH_DATA; - } - - if (!memcmp(buf, "ALPH", TAG_SIZE)) { // A valid ALPH header. - *alpha_data = buf + CHUNK_HEADER_SIZE; - *alpha_size = chunk_size; - } - - // We have a full and valid chunk; skip it. - buf += disk_chunk_size; - buf_size -= disk_chunk_size; - } } int VP8LCheckSignature(const uint8_t* const data, size_t size) { - return (size >= VP8L_FRAME_HEADER_SIZE && data[0] == VP8L_MAGIC_BYTE && - (data[4] >> 5) == 0); // version + return (size >= VP8L_FRAME_HEADER_SIZE && data[0] == VP8L_MAGIC_BYTE && + (data[4] >> 5) == 0); // version } // Validates the VP8/VP8L Header ("VP8 nnnn" or "VP8L nnnn") and skips over it. @@ -198,351 +198,351 @@ int VP8LCheckSignature(const uint8_t* const data, size_t size) { static VP8StatusCode ParseVP8Header(const uint8_t** const data_ptr, size_t* const data_size, int have_all_data, size_t riff_size, size_t* const chunk_size, int* const is_lossless) { - const uint8_t* const data = *data_ptr; - const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); - const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); - const uint32_t minimal_size = TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR - // "WEBP" + "VP8Lnnnn" - assert(data != nullptr); - assert(data_size != nullptr); - assert(chunk_size != nullptr); - assert(is_lossless != nullptr); - - if (*data_size < CHUNK_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. - } - - if (is_vp8 || is_vp8l) { - // Bitstream contains VP8/VP8L header. - const uint32_t size = GetLE32(data + TAG_SIZE); - if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { - return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. + const uint8_t* const data = *data_ptr; + const int is_vp8 = !memcmp(data, "VP8 ", TAG_SIZE); + const int is_vp8l = !memcmp(data, "VP8L", TAG_SIZE); + const uint32_t minimal_size = TAG_SIZE + CHUNK_HEADER_SIZE; // "WEBP" + "VP8 nnnn" OR + // "WEBP" + "VP8Lnnnn" + assert(data != nullptr); + assert(data_size != nullptr); + assert(chunk_size != nullptr); + assert(is_lossless != nullptr); + + if (*data_size < CHUNK_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Insufficient data. } - if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { - return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + + if (is_vp8 || is_vp8l) { + // Bitstream contains VP8/VP8L header. + const uint32_t size = GetLE32(data + TAG_SIZE); + if ((riff_size >= minimal_size) && (size > riff_size - minimal_size)) { + return VP8_STATUS_BITSTREAM_ERROR; // Inconsistent size information. + } + if (have_all_data && (size > *data_size - CHUNK_HEADER_SIZE)) { + return VP8_STATUS_NOT_ENOUGH_DATA; // Truncated bitstream. + } + // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. + *chunk_size = size; + *data_ptr += CHUNK_HEADER_SIZE; + *data_size -= CHUNK_HEADER_SIZE; + *is_lossless = is_vp8l; + } else { + // Raw VP8/VP8L bitstream (no header). + *is_lossless = VP8LCheckSignature(data, *data_size); + *chunk_size = *data_size; } - // Skip over CHUNK_HEADER_SIZE bytes from VP8/VP8L Header. - *chunk_size = size; - *data_ptr += CHUNK_HEADER_SIZE; - *data_size -= CHUNK_HEADER_SIZE; - *is_lossless = is_vp8l; - } else { - // Raw VP8/VP8L bitstream (no header). - *is_lossless = VP8LCheckSignature(data, *data_size); - *chunk_size = *data_size; - } - - return VP8_STATUS_OK; + + return VP8_STATUS_OK; } int VP8CheckSignature(const uint8_t* const data, size_t data_size) { - return (data_size >= 3 && data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); + return (data_size >= 3 && data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a); } int VP8GetInfo(const uint8_t* data, size_t data_size, size_t chunk_size, int* const width, int* const height) { - if (data == nullptr || data_size < VP8_FRAME_HEADER_SIZE) { - return 0; // not enough data - } - // check signature - if (!VP8CheckSignature(data + 3, data_size - 3)) { - return 0; // Wrong signature. - } else { - const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); - const int key_frame = !(bits & 1); - const int w = ((data[7] << 8) | data[6]) & 0x3fff; - const int h = ((data[9] << 8) | data[8]) & 0x3fff; - - if (!key_frame) { // Not a keyframe. - return 0; - } - - if (((bits >> 1) & 7) > 3) { - return 0; // unknown profile - } - if (!((bits >> 4) & 1)) { - return 0; // first frame is invisible! - } - if (((bits >> 5)) >= chunk_size) { // partition_length - return 0; // inconsistent size information. - } - if (w == 0 || h == 0) { - return 0; // We don't support both width and height to be zero. - } - - if (width) { - *width = w; + if (data == nullptr || data_size < VP8_FRAME_HEADER_SIZE) { + return 0; // not enough data } - if (height) { - *height = h; + // check signature + if (!VP8CheckSignature(data + 3, data_size - 3)) { + return 0; // Wrong signature. + } else { + const uint32_t bits = data[0] | (data[1] << 8) | (data[2] << 16); + const int key_frame = !(bits & 1); + const int w = ((data[7] << 8) | data[6]) & 0x3fff; + const int h = ((data[9] << 8) | data[8]) & 0x3fff; + + if (!key_frame) { // Not a keyframe. + return 0; + } + + if (((bits >> 1) & 7) > 3) { + return 0; // unknown profile + } + if (!((bits >> 4) & 1)) { + return 0; // first frame is invisible! + } + if (((bits >> 5)) >= chunk_size) { // partition_length + return 0; // inconsistent size information. + } + if (w == 0 || h == 0) { + return 0; // We don't support both width and height to be zero. + } + + if (width) { + *width = w; + } + if (height) { + *height = h; + } + + return 1; } - - return 1; - } } void VP8LInitBitReader(VP8LBitReader* const br, const uint8_t* const start, size_t length) { - size_t i; - vp8l_val_t value = 0; - assert(br != nullptr); - assert(start != nullptr); - assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. - - br->len_ = length; - br->val_ = 0; - br->bit_pos_ = 0; - br->eos_ = 0; - - if (length > sizeof(br->val_)) { - length = sizeof(br->val_); - } - for (i = 0; i < length; ++i) { - value |= (vp8l_val_t)start[i] << (8 * i); - } - br->val_ = value; - br->pos_ = length; - br->buf_ = start; + size_t i; + vp8l_val_t value = 0; + assert(br != nullptr); + assert(start != nullptr); + assert(length < 0xfffffff8u); // can't happen with a RIFF chunk. + + br->len_ = length; + br->val_ = 0; + br->bit_pos_ = 0; + br->eos_ = 0; + + if (length > sizeof(br->val_)) { + length = sizeof(br->val_); + } + for (i = 0; i < length; ++i) { + value |= (vp8l_val_t)start[i] << (8 * i); + } + br->val_ = value; + br->pos_ = length; + br->buf_ = start; } static WEBP_INLINE uint32_t VP8LPrefetchBits(VP8LBitReader* const br) { - return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); + return (uint32_t)(br->val_ >> (br->bit_pos_ & (VP8L_LBITS - 1))); } static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { - assert(br->pos_ <= br->len_); - return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); + assert(br->pos_ <= br->len_); + return br->eos_ || ((br->pos_ == br->len_) && (br->bit_pos_ > VP8L_LBITS)); } static void VP8LSetEndOfStream(VP8LBitReader* const br) { - br->eos_ = 1; - br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. + br->eos_ = 1; + br->bit_pos_ = 0; // To avoid undefined behaviour with shifts. } // If not at EOS, reload up to VP8L_LBITS byte-by-byte static void ShiftBytes(VP8LBitReader* const br) { - while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { - br->val_ >>= 8; - br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); - ++br->pos_; - br->bit_pos_ -= 8; - } - if (VP8LIsEndOfStream(br)) { - VP8LSetEndOfStream(br); - } + while (br->bit_pos_ >= 8 && br->pos_ < br->len_) { + br->val_ >>= 8; + br->val_ |= ((vp8l_val_t)br->buf_[br->pos_]) << (VP8L_LBITS - 8); + ++br->pos_; + br->bit_pos_ -= 8; + } + if (VP8LIsEndOfStream(br)) { + VP8LSetEndOfStream(br); + } } uint32_t VP8LReadBits(VP8LBitReader* const br, int n_bits) { - assert(n_bits >= 0); - // Flag an error if end_of_stream or n_bits is more than allowed limit. - if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { - const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; - const int new_bits = br->bit_pos_ + n_bits; - br->bit_pos_ = new_bits; - ShiftBytes(br); - return val; - } else { - VP8LSetEndOfStream(br); - return 0; - } + assert(n_bits >= 0); + // Flag an error if end_of_stream or n_bits is more than allowed limit. + if (!br->eos_ && n_bits <= VP8L_MAX_NUM_BIT_READ) { + const uint32_t val = VP8LPrefetchBits(br) & kBitMask[n_bits]; + const int new_bits = br->bit_pos_ + n_bits; + br->bit_pos_ = new_bits; + ShiftBytes(br); + return val; + } else { + VP8LSetEndOfStream(br); + return 0; + } } static int ReadImageInfo(VP8LBitReader* const br, int* const width, int* const height, int* const has_alpha) { - if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; - *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; - *has_alpha = VP8LReadBits(br, 1); - if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; - return !br->eos_; + if (VP8LReadBits(br, 8) != VP8L_MAGIC_BYTE) return 0; + *width = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *height = VP8LReadBits(br, VP8L_IMAGE_SIZE_BITS) + 1; + *has_alpha = VP8LReadBits(br, 1); + if (VP8LReadBits(br, VP8L_VERSION_BITS) != 0) return 0; + return !br->eos_; } int VP8LGetInfo(const uint8_t* data, size_t data_size, int* const width, int* const height, int* const has_alpha) { - if (data == nullptr || data_size < VP8L_FRAME_HEADER_SIZE) { - return 0; // not enough data - } else if (!VP8LCheckSignature(data, data_size)) { - return 0; // bad signature - } else { - int w, h, a; - VP8LBitReader br; - VP8LInitBitReader(&br, data, data_size); - if (!ReadImageInfo(&br, &w, &h, &a)) { - return 0; + if (data == nullptr || data_size < VP8L_FRAME_HEADER_SIZE) { + return 0; // not enough data + } else if (!VP8LCheckSignature(data, data_size)) { + return 0; // bad signature + } else { + int w, h, a; + VP8LBitReader br; + VP8LInitBitReader(&br, data, data_size); + if (!ReadImageInfo(&br, &w, &h, &a)) { + return 0; + } + if (width != nullptr) *width = w; + if (height != nullptr) *height = h; + if (has_alpha != nullptr) *has_alpha = a; + return 1; } - if (width != nullptr) *width = w; - if (height != nullptr) *height = h; - if (has_alpha != nullptr) *has_alpha = a; - return 1; - } } static VP8StatusCode ParseHeadersInternal(const uint8_t* data, size_t data_size, int* const width, - int* const height, int* const has_alpha, - int* const has_animation, int* const format, - WebPHeaderStructure* const headers) { - int canvas_width = 0; - int canvas_height = 0; - int image_width = 0; - int image_height = 0; - int found_riff = 0; - int found_vp8x = 0; - int animation_present = 0; - const int have_all_data = (headers != nullptr) ? headers->have_all_data : 0; - - VP8StatusCode status; - WebPHeaderStructure hdrs; - - if (data == nullptr || data_size < RIFF_HEADER_SIZE) { - return VP8_STATUS_NOT_ENOUGH_DATA; - } - memset(&hdrs, 0, sizeof(hdrs)); - hdrs.data = data; - hdrs.data_size = data_size; - - // Skip over RIFF header. - status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); - if (status != VP8_STATUS_OK) { - return status; // Wrong RIFF header / insufficient data. - } - found_riff = (hdrs.riff_size > 0); - - // Skip over VP8X. - { - uint32_t flags = 0; - status = ParseVP8X(&data, &data_size, &found_vp8x, &canvas_width, &canvas_height, &flags); + int* const height, int* const has_alpha, + int* const has_animation, int* const format, + WebPHeaderStructure* const headers) { + int canvas_width = 0; + int canvas_height = 0; + int image_width = 0; + int image_height = 0; + int found_riff = 0; + int found_vp8x = 0; + int animation_present = 0; + const int have_all_data = (headers != nullptr) ? headers->have_all_data : 0; + + VP8StatusCode status; + WebPHeaderStructure hdrs; + + if (data == nullptr || data_size < RIFF_HEADER_SIZE) { + return VP8_STATUS_NOT_ENOUGH_DATA; + } + memset(&hdrs, 0, sizeof(hdrs)); + hdrs.data = data; + hdrs.data_size = data_size; + + // Skip over RIFF header. + status = ParseRIFF(&data, &data_size, have_all_data, &hdrs.riff_size); if (status != VP8_STATUS_OK) { - return status; // Wrong VP8X / insufficient data. + return status; // Wrong RIFF header / insufficient data. + } + found_riff = (hdrs.riff_size > 0); + + // Skip over VP8X. + { + uint32_t flags = 0; + status = ParseVP8X(&data, &data_size, &found_vp8x, &canvas_width, &canvas_height, &flags); + if (status != VP8_STATUS_OK) { + return status; // Wrong VP8X / insufficient data. + } + animation_present = !!(flags & ANIMATION_FLAG); + if (!found_riff && found_vp8x) { + // Note: This restriction may be removed in the future, if it becomes + // necessary to send VP8X chunk to the decoder. + return VP8_STATUS_BITSTREAM_ERROR; + } + if (has_alpha != nullptr) *has_alpha = !!(flags & ALPHA_FLAG); + if (has_animation != nullptr) *has_animation = animation_present; + if (format != nullptr) *format = 0; // default = undefined + + image_width = canvas_width; + image_height = canvas_height; + if (found_vp8x && animation_present && headers == nullptr) { + status = VP8_STATUS_OK; + goto ReturnWidthHeight; // Just return features from VP8X header. + } } - animation_present = !!(flags & ANIMATION_FLAG); - if (!found_riff && found_vp8x) { - // Note: This restriction may be removed in the future, if it becomes - // necessary to send VP8X chunk to the decoder. - return VP8_STATUS_BITSTREAM_ERROR; + + if (data_size < TAG_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; } - if (has_alpha != nullptr) *has_alpha = !!(flags & ALPHA_FLAG); - if (has_animation != nullptr) *has_animation = animation_present; - if (format != nullptr) *format = 0; // default = undefined - - image_width = canvas_width; - image_height = canvas_height; - if (found_vp8x && animation_present && headers == nullptr) { - status = VP8_STATUS_OK; - goto ReturnWidthHeight; // Just return features from VP8X header. + + // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". + if ((found_riff && found_vp8x) || + (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { + status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, &hdrs.alpha_data, + &hdrs.alpha_data_size); + if (status != VP8_STATUS_OK) { + goto ReturnWidthHeight; // Invalid chunk size / insufficient data. + } } - } - - if (data_size < TAG_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; - } - - // Skip over optional chunks if data started with "RIFF + VP8X" or "ALPH". - if ((found_riff && found_vp8x) || - (!found_riff && !found_vp8x && !memcmp(data, "ALPH", TAG_SIZE))) { - status = ParseOptionalChunks(&data, &data_size, hdrs.riff_size, &hdrs.alpha_data, - &hdrs.alpha_data_size); + + // Skip over VP8/VP8L header. + status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, &hdrs.compressed_size, + &hdrs.is_lossless); if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Invalid chunk size / insufficient data. + goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. } - } - - // Skip over VP8/VP8L header. - status = ParseVP8Header(&data, &data_size, have_all_data, hdrs.riff_size, &hdrs.compressed_size, - &hdrs.is_lossless); - if (status != VP8_STATUS_OK) { - goto ReturnWidthHeight; // Wrong VP8/VP8L chunk-header / insufficient data. - } - if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { - return VP8_STATUS_BITSTREAM_ERROR; - } - - if (format != nullptr && !animation_present) { - *format = hdrs.is_lossless ? 2 : 1; - } - - if (!hdrs.is_lossless) { - if (data_size < VP8_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; + if (hdrs.compressed_size > MAX_CHUNK_PAYLOAD) { + return VP8_STATUS_BITSTREAM_ERROR; } - // Validates raw VP8 data. - if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, &image_width, &image_height)) { - return VP8_STATUS_BITSTREAM_ERROR; + + if (format != nullptr && !animation_present) { + *format = hdrs.is_lossless ? 2 : 1; } - } else { - if (data_size < VP8L_FRAME_HEADER_SIZE) { - status = VP8_STATUS_NOT_ENOUGH_DATA; - goto ReturnWidthHeight; + + if (!hdrs.is_lossless) { + if (data_size < VP8_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8 data. + if (!VP8GetInfo(data, data_size, (uint32_t)hdrs.compressed_size, &image_width, &image_height)) { + return VP8_STATUS_BITSTREAM_ERROR; + } + } else { + if (data_size < VP8L_FRAME_HEADER_SIZE) { + status = VP8_STATUS_NOT_ENOUGH_DATA; + goto ReturnWidthHeight; + } + // Validates raw VP8L data. + if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { + return VP8_STATUS_BITSTREAM_ERROR; + } } - // Validates raw VP8L data. - if (!VP8LGetInfo(data, data_size, &image_width, &image_height, has_alpha)) { - return VP8_STATUS_BITSTREAM_ERROR; + // Validates image size coherency. + if (found_vp8x) { + if (canvas_width != image_width || canvas_height != image_height) { + return VP8_STATUS_BITSTREAM_ERROR; + } } - } - // Validates image size coherency. - if (found_vp8x) { - if (canvas_width != image_width || canvas_height != image_height) { - return VP8_STATUS_BITSTREAM_ERROR; + if (headers != nullptr) { + *headers = hdrs; + headers->offset = data - headers->data; + assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); + assert(headers->offset == headers->data_size - data_size); } - } - if (headers != nullptr) { - *headers = hdrs; - headers->offset = data - headers->data; - assert((uint64_t)(data - headers->data) < MAX_CHUNK_PAYLOAD); - assert(headers->offset == headers->data_size - data_size); - } ReturnWidthHeight: - if (status == VP8_STATUS_OK || - (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == nullptr)) { - if (has_alpha != nullptr) { - // If the data did not contain a VP8X/VP8L chunk the only definitive way - // to set this is by looking for alpha data (from an ALPH chunk). - *has_alpha |= (hdrs.alpha_data != nullptr); + if (status == VP8_STATUS_OK || + (status == VP8_STATUS_NOT_ENOUGH_DATA && found_vp8x && headers == nullptr)) { + if (has_alpha != nullptr) { + // If the data did not contain a VP8X/VP8L chunk the only definitive way + // to set this is by looking for alpha data (from an ALPH chunk). + *has_alpha |= (hdrs.alpha_data != nullptr); + } + if (width != nullptr) *width = image_width; + if (height != nullptr) *height = image_height; + return VP8_STATUS_OK; + } else { + return status; } - if (width != nullptr) *width = image_width; - if (height != nullptr) *height = image_height; - return VP8_STATUS_OK; - } else { - return status; - } } static void DefaultFeatures(WebPBitstreamFeatures* const features) { - assert(features != nullptr); - memset(features, 0, sizeof(*features)); + assert(features != nullptr); + memset(features, 0, sizeof(*features)); } static VP8StatusCode GetFeatures(const uint8_t* const data, size_t data_size, WebPBitstreamFeatures* const features) { - if (features == nullptr || data == nullptr) { - return VP8_STATUS_INVALID_PARAM; - } - DefaultFeatures(features); - - // Only parse enough of the data to retrieve the features. - return ParseHeadersInternal(data, data_size, &features->width, &features->height, - &features->has_alpha, &features->has_animation, &features->format, - nullptr); + if (features == nullptr || data == nullptr) { + return VP8_STATUS_INVALID_PARAM; + } + DefaultFeatures(features); + + // Only parse enough of the data to retrieve the features. + return ParseHeadersInternal(data, data_size, &features->width, &features->height, + &features->has_alpha, &features->has_animation, &features->format, + nullptr); } int WebPGetInfo(const uint8_t* data, size_t data_size, int* width, int* height) { - WebPBitstreamFeatures features = {}; + WebPBitstreamFeatures features = {}; - if (data == nullptr) { - return 0; - } + if (data == nullptr) { + return 0; + } - if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { - return 0; - } + if (GetFeatures(data, data_size, &features) != VP8_STATUS_OK) { + return 0; + } - if (width != nullptr) { - *width = features.width; - } - if (height != nullptr) { - *height = features.height; - } + if (width != nullptr) { + *width = features.width; + } + if (height != nullptr) { + *height = features.height; + } - return 1; + return 1; } } // namespace pag diff --git a/src/codec/utils/WebpDecoder.h b/src/codec/utils/WebpDecoder.h index 17dcdc3b10..b9d9460561 100644 --- a/src/codec/utils/WebpDecoder.h +++ b/src/codec/utils/WebpDecoder.h @@ -40,61 +40,62 @@ namespace pag { typedef uint64_t vp8l_val_t; // right now, this bit-reader can only use 64bit. struct WebPBitstreamFeatures { - int width; // Width in pixels, as read from the bitstream. - int height; // Height in pixels, as read from the bitstream. - int has_alpha; // True if the bitstream contains an alpha channel. - int has_animation; // True if the bitstream is an animation. - int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless + int width; // Width in pixels, as read from the bitstream. + int height; // Height in pixels, as read from the bitstream. + int has_alpha; // True if the bitstream contains an alpha channel. + int has_animation; // True if the bitstream is an animation. + int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless - uint32_t pad[5]; // padding for later use + uint32_t pad[5]; // padding for later use }; typedef enum VP8StatusCode { - VP8_STATUS_OK = 0, - VP8_STATUS_OUT_OF_MEMORY, - VP8_STATUS_INVALID_PARAM, - VP8_STATUS_BITSTREAM_ERROR, - VP8_STATUS_UNSUPPORTED_FEATURE, - VP8_STATUS_SUSPENDED, - VP8_STATUS_USER_ABORT, - VP8_STATUS_NOT_ENOUGH_DATA + VP8_STATUS_OK = 0, + VP8_STATUS_OUT_OF_MEMORY, + VP8_STATUS_INVALID_PARAM, + VP8_STATUS_BITSTREAM_ERROR, + VP8_STATUS_UNSUPPORTED_FEATURE, + VP8_STATUS_SUSPENDED, + VP8_STATUS_USER_ABORT, + VP8_STATUS_NOT_ENOUGH_DATA } VP8StatusCode; typedef struct { - const uint8_t* data; // input buffer - size_t data_size; // input buffer size - int have_all_data; // true if all data is known to be available - size_t offset; // offset to main data chunk (VP8 or VP8L) - const uint8_t* alpha_data; // points to alpha chunk (if present) - size_t alpha_data_size; // alpha chunk size - size_t compressed_size; // VP8/VP8L compressed data size - size_t riff_size; // size of the riff payload (or 0 if absent) - int is_lossless; // true if a VP8L chunk is present + const uint8_t* data; // input buffer + size_t data_size; // input buffer size + int have_all_data; // true if all data is known to be available + size_t offset; // offset to main data chunk (VP8 or VP8L) + const uint8_t* alpha_data; // points to alpha chunk (if present) + size_t alpha_data_size; // alpha chunk size + size_t compressed_size; // VP8/VP8L compressed data size + size_t riff_size; // size of the riff payload (or 0 if absent) + int is_lossless; // true if a VP8L chunk is present } WebPHeaderStructure; typedef enum WebPFeatureFlags { - ANIMATION_FLAG = 0x00000002, - XMP_FLAG = 0x00000004, - EXIF_FLAG = 0x00000008, - ALPHA_FLAG = 0x00000010, - ICCP_FLAG = 0x00000020, + ANIMATION_FLAG = 0x00000002, + XMP_FLAG = 0x00000004, + EXIF_FLAG = 0x00000008, + ALPHA_FLAG = 0x00000010, + ICCP_FLAG = 0x00000020, - ALL_VALID_FLAGS = 0x0000003e + ALL_VALID_FLAGS = 0x0000003e } WebPFeatureFlags; typedef struct { - vp8l_val_t val_; // pre-fetched bits - const uint8_t* buf_; // input byte buffer - size_t len_; // buffer length - size_t pos_; // byte position in buf_ - int bit_pos_; // current bit-reading position in val_ - int eos_; // true if a bit was read past the end of buffer + vp8l_val_t val_; // pre-fetched bits + const uint8_t* buf_; // input byte buffer + size_t len_; // buffer length + size_t pos_; // byte position in buf_ + int bit_pos_; // current bit-reading position in val_ + int eos_; // true if a bit was read past the end of buffer } VP8LBitReader; static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { 0, 0x000001, 0x000003, 0x000007, 0x00000f, 0x00001f, 0x00003f, 0x00007f, 0x0000ff, 0x0001ff, 0x0003ff, 0x0007ff, 0x000fff, 0x001fff, 0x003fff, 0x007fff, 0x00ffff, 0x01ffff, - 0x03ffff, 0x07ffff, 0x0fffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff}; + 0x03ffff, 0x07ffff, 0x0fffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff +}; // Retrieve basic header information: width, height. // This function will also validate the header, returning true on success, diff --git a/src/platform/NativeGLDevice.h b/src/platform/NativeGLDevice.h index 043348a495..8fb382b329 100644 --- a/src/platform/NativeGLDevice.h +++ b/src/platform/NativeGLDevice.h @@ -22,20 +22,20 @@ namespace pag { class NativeGLDevice { - public: - /** - * Returns the native handle of current OpenGL context. - */ - static void* GetCurrentNativeHandle(); +public: + /** + * Returns the native handle of current OpenGL context. + */ + static void* GetCurrentNativeHandle(); - /** - * Returns a offscreen device with adopted current OpenGL context. - */ - static std::shared_ptr Current(); + /** + * Returns a offscreen device with adopted current OpenGL context. + */ + static std::shared_ptr Current(); - /** - * Creates an offscreen device with specified shared OpenGL context. - */ - static std::shared_ptr Make(void* sharedContext = nullptr); + /** + * Creates an offscreen device with specified shared OpenGL context. + */ + static std::shared_ptr Make(void* sharedContext = nullptr); }; } // namespace pag diff --git a/src/platform/Platform.cpp b/src/platform/Platform.cpp index ba464e5bd0..7c4ec1f3b7 100644 --- a/src/platform/Platform.cpp +++ b/src/platform/Platform.cpp @@ -26,58 +26,58 @@ namespace pag { bool Platform::hasHardwareDecoder() const { - return false; + return false; } std::unique_ptr Platform::makeHardwareDecoder(const VideoConfig&) const { - return nullptr; + return nullptr; } std::shared_ptr Platform::makeHardwareBuffer(int, int, bool) const { - return nullptr; + return nullptr; } std::shared_ptr Platform::makeImage(const std::string&) const { - return nullptr; + return nullptr; } std::shared_ptr Platform::makeImage(std::shared_ptr) const { - return nullptr; + return nullptr; } PAGFont Platform::parseFont(const std::string&, int) const { - return {"", ""}; + return {"", ""}; } PAGFont Platform::parseFont(const void*, size_t, int) const { - return {"", ""}; + return {"", ""}; } void Platform::printLog(const char format[], ...) const { - va_list args; - va_start(args, format); - vfprintf(stdout, format, args); - va_end(args); - fprintf(stdout, "\n"); + va_list args; + va_start(args, format); + vfprintf(stdout, format, args); + va_end(args); + fprintf(stdout, "\n"); } void Platform::printError(const char format[], ...) const { - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - fprintf(stderr, "\n"); + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); } bool Platform::registerFallbackFonts() const { - return false; + return false; } void Platform::reportStatisticalData(std::unordered_map&) const { } NALUType Platform::naluType() const { - return NALUType::AnnexB; + return NALUType::AnnexB; } void Platform::traceImage(const PixelMap&, const std::string&) const { diff --git a/src/platform/Platform.h b/src/platform/Platform.h index 8c27524ce8..4eae7103c2 100644 --- a/src/platform/Platform.h +++ b/src/platform/Platform.h @@ -38,88 +38,88 @@ class Data; * Defines methods for native platforms to implement. */ class Platform { - public: - /** - * Returns the instance of current platform. - */ - static const Platform* Current(); - - virtual ~Platform() = default; - - /** - * Returns true if hardware video decoders are supported on current platform. - */ - virtual bool hasHardwareDecoder() const; - - /** - * Creates a hardware backed VideoDecoder with the specified video config. Returns nullptr if - * current platform has no hardware decoder support. - */ - virtual std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const; - - /** - * Creates a hardware backed PixelBuffer with specified width and height. Returns nullptr if - * current platform has no hardware buffer support. Hardware buffer is a low-level object - * representing a memory buffer accessible by various hardware units. Hardware buffer allows - * sharing buffers across CPU and GPU, which can be used to speed up the texture uploading. - */ - virtual std::shared_ptr makeHardwareBuffer(int width, int height, - bool alphaOnly) const; - - /** - * If the file path represents an encoded image that current platform knows how to decode, returns - * an Image that can decode it. Otherwise returns nullptr. - */ - virtual std::shared_ptr makeImage(const std::string& filePath) const; - - /** - * If the file bytes represents an encoded image that current platform knows how to decode, - * returns an Image that can decode it. Otherwise returns nullptr. - */ - virtual std::shared_ptr makeImage(std::shared_ptr imageBytes) const; - - /** - * Parses the font family and style from specified file path. Returns a font data with empty - * family and style names if the file path is not a valid font. - */ - virtual PAGFont parseFont(const std::string& fontPath, int ttcIndex) const; - - /** - * Parses the font family and style from specified file bytes. Returns a font data with empty - * family and style names if the file bytes is not a valid font. - */ - virtual PAGFont parseFont(const void* data, size_t length, int ttcIndex) const; - - /** - * Writes the string pointed by format to the standard output (stdout). - */ - virtual void printLog(const char format[], ...) const; - - /** - * Writes the string pointed by format to the standard error (stderr). - */ - virtual void printError(const char format[], ...) const; - - /** - * Implement this method to register the default fallback font list. User should call - * PAGFont::SetFallbackFontPaths() or PAGFont::SetFallbackFontNames() manually in host app if this - * method is not implemented on current platform. - */ - virtual bool registerFallbackFonts() const; - - /** - * Reports the statistical data of pag. - */ - virtual void reportStatisticalData(std::unordered_map& reportMap) const; - - /** - * Returns the default NALU start code type of the current platform. - */ - virtual NALUType naluType() const; - - /** - * Provides a utility to view the PixelMap data. - */ - virtual void traceImage(const PixelMap& pixelMap, const std::string& tag) const; +public: + /** + * Returns the instance of current platform. + */ + static const Platform* Current(); + + virtual ~Platform() = default; + + /** + * Returns true if hardware video decoders are supported on current platform. + */ + virtual bool hasHardwareDecoder() const; + + /** + * Creates a hardware backed VideoDecoder with the specified video config. Returns nullptr if + * current platform has no hardware decoder support. + */ + virtual std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const; + + /** + * Creates a hardware backed PixelBuffer with specified width and height. Returns nullptr if + * current platform has no hardware buffer support. Hardware buffer is a low-level object + * representing a memory buffer accessible by various hardware units. Hardware buffer allows + * sharing buffers across CPU and GPU, which can be used to speed up the texture uploading. + */ + virtual std::shared_ptr makeHardwareBuffer(int width, int height, + bool alphaOnly) const; + + /** + * If the file path represents an encoded image that current platform knows how to decode, returns + * an Image that can decode it. Otherwise returns nullptr. + */ + virtual std::shared_ptr makeImage(const std::string& filePath) const; + + /** + * If the file bytes represents an encoded image that current platform knows how to decode, + * returns an Image that can decode it. Otherwise returns nullptr. + */ + virtual std::shared_ptr makeImage(std::shared_ptr imageBytes) const; + + /** + * Parses the font family and style from specified file path. Returns a font data with empty + * family and style names if the file path is not a valid font. + */ + virtual PAGFont parseFont(const std::string& fontPath, int ttcIndex) const; + + /** + * Parses the font family and style from specified file bytes. Returns a font data with empty + * family and style names if the file bytes is not a valid font. + */ + virtual PAGFont parseFont(const void* data, size_t length, int ttcIndex) const; + + /** + * Writes the string pointed by format to the standard output (stdout). + */ + virtual void printLog(const char format[], ...) const; + + /** + * Writes the string pointed by format to the standard error (stderr). + */ + virtual void printError(const char format[], ...) const; + + /** + * Implement this method to register the default fallback font list. User should call + * PAGFont::SetFallbackFontPaths() or PAGFont::SetFallbackFontNames() manually in host app if this + * method is not implemented on current platform. + */ + virtual bool registerFallbackFonts() const; + + /** + * Reports the statistical data of pag. + */ + virtual void reportStatisticalData(std::unordered_map& reportMap) const; + + /** + * Returns the default NALU start code type of the current platform. + */ + virtual NALUType naluType() const; + + /** + * Provides a utility to view the PixelMap data. + */ + virtual void traceImage(const PixelMap& pixelMap, const std::string& tag) const; }; } // namespace pag \ No newline at end of file diff --git a/src/platform/android/FontConfigAndroid.cpp b/src/platform/android/FontConfigAndroid.cpp index acc1b37ecb..3906a03f61 100644 --- a/src/platform/android/FontConfigAndroid.cpp +++ b/src/platform/android/FontConfigAndroid.cpp @@ -32,86 +32,86 @@ static jmethodID PAGFont_RegisterFallbackFonts; extern "C" { -void FontConfigAndroid::InitJNI(JNIEnv* env) { - PAGFontClass.reset(env, env->FindClass("org/libpag/PAGFont")); - if (PAGFontClass.get() == nullptr) { - LOGE("Could not run PAGFont.RegisterFallbackFonts(), class is not found!"); - return; - } - PAGFont_RegisterFallbackFonts = - env->GetStaticMethodID(PAGFontClass.get(), "RegisterFallbackFonts", "()V"); -} + void FontConfigAndroid::InitJNI(JNIEnv* env) { + PAGFontClass.reset(env, env->FindClass("org/libpag/PAGFont")); + if (PAGFontClass.get() == nullptr) { + LOGE("Could not run PAGFont.RegisterFallbackFonts(), class is not found!"); + return; + } + PAGFont_RegisterFallbackFonts = + env->GetStaticMethodID(PAGFontClass.get(), "RegisterFallbackFonts", "()V"); + } -bool FontConfigAndroid::RegisterFallbackFonts() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - if (PAGFontClass.get() == nullptr) { - LOGE("PAGFontClass is null"); - return false; - } - env->CallStaticVoidMethod(PAGFontClass.get(), PAGFont_RegisterFallbackFonts); - return true; -} + bool FontConfigAndroid::RegisterFallbackFonts() { + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return false; + } + if (PAGFontClass.get() == nullptr) { + LOGE("PAGFontClass is null"); + return false; + } + env->CallStaticVoidMethod(PAGFontClass.get(), PAGFont_RegisterFallbackFonts); + return true; + } -static void* ft_alloc(FT_Memory, long size) { - return malloc(static_cast(size)); -} -static void ft_free(FT_Memory, void* block) { - free(block); -} -static void* ft_realloc(FT_Memory, long, long new_size, void* block) { - return realloc(block, static_cast(new_size)); -} + static void* ft_alloc(FT_Memory, long size) { + return malloc(static_cast(size)); + } + static void ft_free(FT_Memory, void* block) { + free(block); + } + static void* ft_realloc(FT_Memory, long, long new_size, void* block) { + return realloc(block, static_cast(new_size)); + } } static FT_MemoryRec_ gFTMemory = {nullptr, ft_alloc, ft_free, ft_realloc}; static PAGFont ParseFont(const FT_Open_Args* args, int ttcIndex) { - if (args == nullptr) { - return {"", ""}; - } - FT_Library fLibrary = nullptr; - if (FT_New_Library(&gFTMemory, &fLibrary)) { - return {"", ""}; - } - FT_Add_Default_Modules(fLibrary); - FT_Face face; - if (FT_Open_Face(fLibrary, args, ttcIndex, &face)) { + if (args == nullptr) { + return {"", ""}; + } + FT_Library fLibrary = nullptr; + if (FT_New_Library(&gFTMemory, &fLibrary)) { + return {"", ""}; + } + FT_Add_Default_Modules(fLibrary); + FT_Face face; + if (FT_Open_Face(fLibrary, args, ttcIndex, &face)) { + FT_Done_Library(fLibrary); + return {"", ""}; + } + if (face->family_name == nullptr) { + return {"", ""}; + } + std::string fontFamily = face->family_name; + std::string fontStyle = face->style_name; + FT_Done_Face(face); FT_Done_Library(fLibrary); - return {"", ""}; - } - if (face->family_name == nullptr) { - return {"", ""}; - } - std::string fontFamily = face->family_name; - std::string fontStyle = face->style_name; - FT_Done_Face(face); - FT_Done_Library(fLibrary); - return {fontFamily, fontStyle}; + return {fontFamily, fontStyle}; } PAGFont FontConfigAndroid::Parse(const void* data, size_t length, int ttcIndex) { - if (length == 0) { - return {"", ""}; - } - FT_Open_Args args = {}; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_MEMORY; - args.memory_base = (const FT_Byte*)data; - args.memory_size = static_cast(length); - return ParseFont(&args, ttcIndex); + if (length == 0) { + return {"", ""}; + } + FT_Open_Args args = {}; + memset(&args, 0, sizeof(args)); + args.flags = FT_OPEN_MEMORY; + args.memory_base = (const FT_Byte*)data; + args.memory_size = static_cast(length); + return ParseFont(&args, ttcIndex); } PAGFont FontConfigAndroid::Parse(const std::string& fontPath, int ttcIndex) { - if (fontPath.empty()) { - return {"", ""}; - } - FT_Open_Args args = {}; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_PATHNAME; - args.pathname = const_cast(fontPath.c_str()); - return ParseFont(&args, ttcIndex); + if (fontPath.empty()) { + return {"", ""}; + } + FT_Open_Args args = {}; + memset(&args, 0, sizeof(args)); + args.flags = FT_OPEN_PATHNAME; + args.pathname = const_cast(fontPath.c_str()); + return ParseFont(&args, ttcIndex); } } // namespace pag diff --git a/src/platform/android/FontConfigAndroid.h b/src/platform/android/FontConfigAndroid.h index 53c1e6cbfb..c43d44980e 100644 --- a/src/platform/android/FontConfigAndroid.h +++ b/src/platform/android/FontConfigAndroid.h @@ -23,18 +23,18 @@ namespace pag { class FontConfigAndroid { - public: - /** - * FindClass method will cause a crash when called in non-main thread. - * So must call this method in main thread before use RegisterFallbackFonts. - * @param env - */ - static void InitJNI(JNIEnv* env); +public: + /** + * FindClass method will cause a crash when called in non-main thread. + * So must call this method in main thread before use RegisterFallbackFonts. + * @param env + */ + static void InitJNI(JNIEnv* env); - static bool RegisterFallbackFonts(); + static bool RegisterFallbackFonts(); - static PAGFont Parse(const void* data, size_t length, int ttcIndex); + static PAGFont Parse(const void* data, size_t length, int ttcIndex); - static PAGFont Parse(const std::string& fontPath, int ttcIndex); + static PAGFont Parse(const std::string& fontPath, int ttcIndex); }; } // namespace pag diff --git a/src/platform/android/GLHardwareTexture.cpp b/src/platform/android/GLHardwareTexture.cpp index 236e347425..56f269de2d 100644 --- a/src/platform/android/GLHardwareTexture.cpp +++ b/src/platform/android/GLHardwareTexture.cpp @@ -35,91 +35,91 @@ using namespace glext; std::once_flag sApiLevelOnceFlag; static bool initGlextProc() { - std::call_once(sApiLevelOnceFlag, []() { - glext::eglGetNativeClientBufferANDROID = - (PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC)eglGetProcAddress( - "eglGetNativeClientBufferANDROID"); - // for AHardwareBuffer - glext::glEGLImageTargetTexture2DOES = - (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - glext::eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); - glext::eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); - }); - return glext::glEGLImageTargetTexture2DOES && glext::eglCreateImageKHR && - glext::eglDestroyImageKHR; + std::call_once(sApiLevelOnceFlag, []() { + glext::eglGetNativeClientBufferANDROID = + (PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC)eglGetProcAddress( + "eglGetNativeClientBufferANDROID"); + // for AHardwareBuffer + glext::glEGLImageTargetTexture2DOES = + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + glext::eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); + glext::eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); + }); + return glext::glEGLImageTargetTexture2DOES && glext::eglCreateImageKHR && + glext::eglDestroyImageKHR; } std::shared_ptr GLHardwareTexture::MakeFrom( Context* context, android::GraphicBuffer* graphicBuffer) { - std::shared_ptr glTexture = nullptr; - BytesKey recycleKey = {}; - GLHardwareTexture::ComputeRecycleKey(&recycleKey, graphicBuffer); - glTexture = std::static_pointer_cast(context->getRecycledResource(recycleKey)); - if (glTexture) { - return glTexture; - } - auto buffer = - ((android::android_native_buffer_t*)NativeGraphicBufferInterface::Get()->getNativeBuffer( - graphicBuffer)); - if (!buffer) { - return nullptr; - } - return GLHardwareTexture::MakeFrom(context, nullptr, graphicBuffer, buffer, buffer->width, - buffer->height); + std::shared_ptr glTexture = nullptr; + BytesKey recycleKey = {}; + GLHardwareTexture::ComputeRecycleKey(&recycleKey, graphicBuffer); + glTexture = std::static_pointer_cast(context->getRecycledResource(recycleKey)); + if (glTexture) { + return glTexture; + } + auto buffer = + ((android::android_native_buffer_t*)NativeGraphicBufferInterface::Get()->getNativeBuffer( + graphicBuffer)); + if (!buffer) { + return nullptr; + } + return GLHardwareTexture::MakeFrom(context, nullptr, graphicBuffer, buffer, buffer->width, + buffer->height); } std::shared_ptr GLHardwareTexture::MakeFrom( Context* context, AHardwareBuffer* hardwareBuffer) { - if (!hardwareBuffer) { - return nullptr; - } - static bool init = initGlextProc() && glext::eglGetNativeClientBufferANDROID; - if (!init) { - return nullptr; - } - std::shared_ptr glTexture = nullptr; - BytesKey recycleKey = {}; - ComputeRecycleKey(&recycleKey, hardwareBuffer); - glTexture = std::static_pointer_cast(context->getRecycledResource(recycleKey)); - if (glTexture) { - return glTexture; - } - // Convert the AHardwareBuffer to EGLImage. - EGLClientBuffer clientBuffer = glext::eglGetNativeClientBufferANDROID(hardwareBuffer); - if (!clientBuffer) { - return nullptr; - } - AHardwareBuffer_Desc desc; - NativeHardwareBufferInterface::Get()->AHardwareBuffer_describe(hardwareBuffer, &desc); - return MakeFrom(context, hardwareBuffer, nullptr, clientBuffer, desc.width, desc.height); + if (!hardwareBuffer) { + return nullptr; + } + static bool init = initGlextProc() && glext::eglGetNativeClientBufferANDROID; + if (!init) { + return nullptr; + } + std::shared_ptr glTexture = nullptr; + BytesKey recycleKey = {}; + ComputeRecycleKey(&recycleKey, hardwareBuffer); + glTexture = std::static_pointer_cast(context->getRecycledResource(recycleKey)); + if (glTexture) { + return glTexture; + } + // Convert the AHardwareBuffer to EGLImage. + EGLClientBuffer clientBuffer = glext::eglGetNativeClientBufferANDROID(hardwareBuffer); + if (!clientBuffer) { + return nullptr; + } + AHardwareBuffer_Desc desc; + NativeHardwareBufferInterface::Get()->AHardwareBuffer_describe(hardwareBuffer, &desc); + return MakeFrom(context, hardwareBuffer, nullptr, clientBuffer, desc.width, desc.height); } std::shared_ptr GLHardwareTexture::MakeFrom( Context* context, AHardwareBuffer* hardwareBuffer, android::GraphicBuffer* graphicBuffer, EGLClientBuffer clientBuffer, int width, int height) { - static bool init = initGlextProc(); - if (!init || !clientBuffer) { - return nullptr; - } - EGLDisplay disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); - EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = glext::eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - clientBuffer, eglImageAttributes); - if (eglImage == EGL_NO_IMAGE_KHR) return nullptr; - GLTextureInfo glInfo = {}; - glGenTextures(1, &glInfo.id); - glBindTexture(GL_TEXTURE_2D, glInfo.id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glext::glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); - auto glTexture = Resource::Wrap( - context, new GLHardwareTexture(hardwareBuffer, graphicBuffer, eglImage, width, height)); - glTexture->sampler.glInfo = glInfo; - glTexture->sampler.config = PixelConfig::RGBA_8888; - return glTexture; + static bool init = initGlextProc(); + if (!init || !clientBuffer) { + return nullptr; + } + EGLDisplay disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + EGLImageKHR eglImage = glext::eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + clientBuffer, eglImageAttributes); + if (eglImage == EGL_NO_IMAGE_KHR) return nullptr; + GLTextureInfo glInfo = {}; + glGenTextures(1, &glInfo.id); + glBindTexture(GL_TEXTURE_2D, glInfo.id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glext::glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); + auto glTexture = Resource::Wrap( + context, new GLHardwareTexture(hardwareBuffer, graphicBuffer, eglImage, width, height)); + glTexture->sampler.glInfo = glInfo; + glTexture->sampler.config = PixelConfig::RGBA_8888; + return glTexture; } GLHardwareTexture::GLHardwareTexture(AHardwareBuffer* hardwareBuffer, @@ -129,35 +129,35 @@ GLHardwareTexture::GLHardwareTexture(AHardwareBuffer* hardwareBuffer, _eglImage(eglImage), hardwareBuffer(hardwareBuffer), graphicBuffer(graphicBuffer) { - if (graphicBuffer) { - NativeGraphicBufferInterface::Acquire(graphicBuffer); - } - if (hardwareBuffer) { - NativeHardwareBufferInterface::Get()->AHardwareBuffer_acquire(hardwareBuffer); - } + if (graphicBuffer) { + NativeGraphicBufferInterface::Acquire(graphicBuffer); + } + if (hardwareBuffer) { + NativeHardwareBufferInterface::Get()->AHardwareBuffer_acquire(hardwareBuffer); + } } void GLHardwareTexture::ComputeRecycleKey(BytesKey* recycleKey, void* hardware_buffer) { - static const uint32_t BGRAType = UniqueID::Next(); - recycleKey->write(BGRAType); - recycleKey->write(hardware_buffer); + static const uint32_t BGRAType = UniqueID::Next(); + recycleKey->write(BGRAType); + recycleKey->write(hardware_buffer); } void GLHardwareTexture::onRelease(Context* context) { - if (sampler.glInfo.id > 0) { - auto gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); - } - EGLDisplay disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (_eglImage != EGL_NO_IMAGE_KHR) { - glext::eglDestroyImageKHR(disp, _eglImage); - _eglImage = EGL_NO_IMAGE_KHR; - } - if (hardwareBuffer) { - NativeHardwareBufferInterface::Get()->AHardwareBuffer_release(hardwareBuffer); - } - if (graphicBuffer) { - NativeGraphicBufferInterface::Release(graphicBuffer); - } + if (sampler.glInfo.id > 0) { + auto gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &sampler.glInfo.id); + } + EGLDisplay disp = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (_eglImage != EGL_NO_IMAGE_KHR) { + glext::eglDestroyImageKHR(disp, _eglImage); + _eglImage = EGL_NO_IMAGE_KHR; + } + if (hardwareBuffer) { + NativeHardwareBufferInterface::Get()->AHardwareBuffer_release(hardwareBuffer); + } + if (graphicBuffer) { + NativeGraphicBufferInterface::Release(graphicBuffer); + } } } // namespace pag diff --git a/src/platform/android/GLHardwareTexture.h b/src/platform/android/GLHardwareTexture.h index 83743f4703..75726c8452 100644 --- a/src/platform/android/GLHardwareTexture.h +++ b/src/platform/android/GLHardwareTexture.h @@ -28,29 +28,29 @@ namespace pag { class GLHardwareTexture : public GLTexture { - public: - static std::shared_ptr MakeFrom( - Context* context, AHardwareBuffer* hardwareBuffer); - static std::shared_ptr MakeFrom( - Context* context, android::GraphicBuffer* graphicBuffer); +public: + static std::shared_ptr MakeFrom( + Context* context, AHardwareBuffer* hardwareBuffer); + static std::shared_ptr MakeFrom( + Context* context, android::GraphicBuffer* graphicBuffer); - static std::shared_ptr MakeFrom( - Context* context, AHardwareBuffer* hardwareBuffer, - android::GraphicBuffer* graphicBuffer, EGLClientBuffer client_buffer, int width, - int height); + static std::shared_ptr MakeFrom( + Context* context, AHardwareBuffer* hardwareBuffer, + android::GraphicBuffer* graphicBuffer, EGLClientBuffer client_buffer, int width, + int height); - size_t memoryUsage() const override { - return 0; - } + size_t memoryUsage() const override { + return 0; + } - private: - explicit GLHardwareTexture(AHardwareBuffer* hardwareBuffer, - android::GraphicBuffer* graphicBuffer, EGLImageKHR eglImage, - int width, int height); - EGLImageKHR _eglImage = EGL_NO_IMAGE_KHR; - AHardwareBuffer* hardwareBuffer = nullptr; - android::GraphicBuffer* graphicBuffer = nullptr; - void onRelease(Context* context) override; - static void ComputeRecycleKey(BytesKey* recycleKey, void* hardware_buffer); +private: + explicit GLHardwareTexture(AHardwareBuffer* hardwareBuffer, + android::GraphicBuffer* graphicBuffer, EGLImageKHR eglImage, + int width, int height); + EGLImageKHR _eglImage = EGL_NO_IMAGE_KHR; + AHardwareBuffer* hardwareBuffer = nullptr; + android::GraphicBuffer* graphicBuffer = nullptr; + void onRelease(Context* context) override; + static void ComputeRecycleKey(BytesKey* recycleKey, void* hardware_buffer); }; } // namespace pag diff --git a/src/platform/android/GPUDecoder.cpp b/src/platform/android/GPUDecoder.cpp index 7b274867af..279e6de306 100644 --- a/src/platform/android/GPUDecoder.cpp +++ b/src/platform/android/GPUDecoder.cpp @@ -37,174 +37,174 @@ static jmethodID MediaFormat_setByteBuffer; static jmethodID MediaFormat_setFloat; void GPUDecoder::InitJNI(JNIEnv* env, const std::string& className) { - GPUDecoderClass.reset(env, env->FindClass(className.c_str())); - std::string createSig = std::string("(Landroid/view/Surface;)L") + className + ";"; - GPUDecoder_Create = env->GetStaticMethodID(GPUDecoderClass.get(), "Create", createSig.c_str()); - GPUDecoder_onConfigure = - env->GetMethodID(GPUDecoderClass.get(), "onConfigure", "(Landroid/media/MediaFormat;)Z"); - GPUDecoder_onSendBytes = - env->GetMethodID(GPUDecoderClass.get(), "onSendBytes", "(Ljava/nio/ByteBuffer;J)I"); - GPUDecoder_onEndOfStream = env->GetMethodID(GPUDecoderClass.get(), "onEndOfStream", "()I"); - GPUDecoder_onDecodeFrame = env->GetMethodID(GPUDecoderClass.get(), "onDecodeFrame", "()I"); - GPUDecoder_onFlush = env->GetMethodID(GPUDecoderClass.get(), "onFlush", "()V"); - GPUDecoder_presentationTime = env->GetMethodID(GPUDecoderClass.get(), "presentationTime", "()J"); - GPUDecoder_onRenderFrame = env->GetMethodID(GPUDecoderClass.get(), "onRenderFrame", "()Z"); - GPUDecoder_onRelease = env->GetMethodID(GPUDecoderClass.get(), "onRelease", "()V"); + GPUDecoderClass.reset(env, env->FindClass(className.c_str())); + std::string createSig = std::string("(Landroid/view/Surface;)L") + className + ";"; + GPUDecoder_Create = env->GetStaticMethodID(GPUDecoderClass.get(), "Create", createSig.c_str()); + GPUDecoder_onConfigure = + env->GetMethodID(GPUDecoderClass.get(), "onConfigure", "(Landroid/media/MediaFormat;)Z"); + GPUDecoder_onSendBytes = + env->GetMethodID(GPUDecoderClass.get(), "onSendBytes", "(Ljava/nio/ByteBuffer;J)I"); + GPUDecoder_onEndOfStream = env->GetMethodID(GPUDecoderClass.get(), "onEndOfStream", "()I"); + GPUDecoder_onDecodeFrame = env->GetMethodID(GPUDecoderClass.get(), "onDecodeFrame", "()I"); + GPUDecoder_onFlush = env->GetMethodID(GPUDecoderClass.get(), "onFlush", "()V"); + GPUDecoder_presentationTime = env->GetMethodID(GPUDecoderClass.get(), "presentationTime", "()J"); + GPUDecoder_onRenderFrame = env->GetMethodID(GPUDecoderClass.get(), "onRenderFrame", "()Z"); + GPUDecoder_onRelease = env->GetMethodID(GPUDecoderClass.get(), "onRelease", "()V"); - MediaFormatClass.reset(env, env->FindClass("android/media/MediaFormat")); - MediaFormat_createVideoFormat = - env->GetStaticMethodID(MediaFormatClass.get(), "createVideoFormat", - "(Ljava/lang/String;II)Landroid/media/MediaFormat;"); - MediaFormat_setByteBuffer = env->GetMethodID(MediaFormatClass.get(), "setByteBuffer", - "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V"); - MediaFormat_setFloat = env->GetMethodID(MediaFormatClass.get(), "setFloat", - "(Ljava/lang/String;F)V"); + MediaFormatClass.reset(env, env->FindClass("android/media/MediaFormat")); + MediaFormat_createVideoFormat = + env->GetStaticMethodID(MediaFormatClass.get(), "createVideoFormat", + "(Ljava/lang/String;II)Landroid/media/MediaFormat;"); + MediaFormat_setByteBuffer = env->GetMethodID(MediaFormatClass.get(), "setByteBuffer", + "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V"); + MediaFormat_setFloat = env->GetMethodID(MediaFormatClass.get(), "setFloat", + "(Ljava/lang/String;F)V"); } GPUDecoder::GPUDecoder(const VideoConfig& config) { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return; - } - videoSurface = VideoSurface::Make(config.width, config.height, config.hasAlpha); - if (videoSurface == nullptr) { - return; - } - jobject outputSurface = videoSurface->getOutputSurface(env); - jobject decoder = - env->CallStaticObjectMethod(GPUDecoderClass.get(), GPUDecoder_Create, outputSurface); - env->DeleteLocalRef(outputSurface); - if (decoder == nullptr) { - _isValid = false; - return; - } - videoDecoder.reset(env, decoder); - _isValid = onConfigure(decoder, config); - env->DeleteLocalRef(decoder); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + videoSurface = VideoSurface::Make(config.width, config.height, config.hasAlpha); + if (videoSurface == nullptr) { + return; + } + jobject outputSurface = videoSurface->getOutputSurface(env); + jobject decoder = + env->CallStaticObjectMethod(GPUDecoderClass.get(), GPUDecoder_Create, outputSurface); + env->DeleteLocalRef(outputSurface); + if (decoder == nullptr) { + _isValid = false; + return; + } + videoDecoder.reset(env, decoder); + _isValid = onConfigure(decoder, config); + env->DeleteLocalRef(decoder); } GPUDecoder::~GPUDecoder() { - if (videoDecoder.get() != nullptr) { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return; + if (videoDecoder.get() != nullptr) { + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + env->CallVoidMethod(videoDecoder.get(), GPUDecoder_onRelease); } - env->CallVoidMethod(videoDecoder.get(), GPUDecoder_onRelease); - } } bool GPUDecoder::onConfigure(jobject decoder, const VideoConfig& config) { - videoWidth = config.width; - videoHeight = config.height; - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - jstring mimeType = SafeConvertToJString(env, config.mimeType.c_str()); - auto mediaFormat = env->CallStaticObjectMethod( - MediaFormatClass.get(), MediaFormat_createVideoFormat, mimeType, config.width, config.height); - env->DeleteLocalRef(mimeType); - if (config.mimeType == "video/hevc") { - if (!config.headers.empty()) { - char keyString[] = "csd-0"; - auto key = SafeConvertToJString(env, keyString); - int dataLength = 0; - for (auto& header : config.headers) { - dataLength += header->length(); - } - auto data = new uint8_t[dataLength]; - int index = 0; - for (auto& header : config.headers) { - memcpy(data + index, header->data(), header->length()); - index += header->length(); - } - auto bytes = env->NewDirectByteBuffer(data, dataLength); - env->CallVoidMethod(mediaFormat, MediaFormat_setByteBuffer, key, bytes); - env->DeleteLocalRef(key); - env->DeleteLocalRef(bytes); - delete[] data; + videoWidth = config.width; + videoHeight = config.height; + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return false; } - } else { - int index = 0; - for (auto& header : config.headers) { - char keyString[6]; - snprintf(keyString, 6, "csd-%d", index); - auto key = SafeConvertToJString(env, keyString); - auto bytes = env->NewDirectByteBuffer(header->data(), header->length()); - env->CallVoidMethod(mediaFormat, MediaFormat_setByteBuffer, key, bytes); - env->DeleteLocalRef(key); - env->DeleteLocalRef(bytes); - index++; + jstring mimeType = SafeConvertToJString(env, config.mimeType.c_str()); + auto mediaFormat = env->CallStaticObjectMethod( + MediaFormatClass.get(), MediaFormat_createVideoFormat, mimeType, config.width, config.height); + env->DeleteLocalRef(mimeType); + if (config.mimeType == "video/hevc") { + if (!config.headers.empty()) { + char keyString[] = "csd-0"; + auto key = SafeConvertToJString(env, keyString); + int dataLength = 0; + for (auto& header : config.headers) { + dataLength += header->length(); + } + auto data = new uint8_t[dataLength]; + int index = 0; + for (auto& header : config.headers) { + memcpy(data + index, header->data(), header->length()); + index += header->length(); + } + auto bytes = env->NewDirectByteBuffer(data, dataLength); + env->CallVoidMethod(mediaFormat, MediaFormat_setByteBuffer, key, bytes); + env->DeleteLocalRef(key); + env->DeleteLocalRef(bytes); + delete[] data; + } + } else { + int index = 0; + for (auto& header : config.headers) { + char keyString[6]; + snprintf(keyString, 6, "csd-%d", index); + auto key = SafeConvertToJString(env, keyString); + auto bytes = env->NewDirectByteBuffer(header->data(), header->length()); + env->CallVoidMethod(mediaFormat, MediaFormat_setByteBuffer, key, bytes); + env->DeleteLocalRef(key); + env->DeleteLocalRef(bytes); + index++; + } } - } - char frameRateKeyString[] = "frame-rate"; - auto frameRateKey = SafeConvertToJString(env, frameRateKeyString); - env->CallVoidMethod(mediaFormat, MediaFormat_setFloat, frameRateKey, config.frameRate); - env->DeleteLocalRef(frameRateKey); - auto result = env->CallBooleanMethod(decoder, GPUDecoder_onConfigure, mediaFormat); - env->DeleteLocalRef(mediaFormat); + char frameRateKeyString[] = "frame-rate"; + auto frameRateKey = SafeConvertToJString(env, frameRateKeyString); + env->CallVoidMethod(mediaFormat, MediaFormat_setFloat, frameRateKey, config.frameRate); + env->DeleteLocalRef(frameRateKey); + auto result = env->CallBooleanMethod(decoder, GPUDecoder_onConfigure, mediaFormat); + env->DeleteLocalRef(mediaFormat); - return result; + return result; } DecodingResult GPUDecoder::onSendBytes(void* bytes, size_t length, int64_t time) { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - LOGE("GPUDecoder: Error on sending bytes for decoding.\n"); - return pag::DecodingResult::Error; - } - auto byteBuffer = env->NewDirectByteBuffer(bytes, length); - auto result = env->CallIntMethod(videoDecoder.get(), GPUDecoder_onSendBytes, byteBuffer, time); - env->DeleteLocalRef(byteBuffer); - return static_cast(result); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + LOGE("GPUDecoder: Error on sending bytes for decoding.\n"); + return pag::DecodingResult::Error; + } + auto byteBuffer = env->NewDirectByteBuffer(bytes, length); + auto result = env->CallIntMethod(videoDecoder.get(), GPUDecoder_onSendBytes, byteBuffer, time); + env->DeleteLocalRef(byteBuffer); + return static_cast(result); } DecodingResult GPUDecoder::onDecodeFrame() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - LOGE("GPUDecoder: Error on decoding frame.\n"); - return pag::DecodingResult::Error; - } - return static_cast( - env->CallIntMethod(videoDecoder.get(), GPUDecoder_onDecodeFrame)); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + LOGE("GPUDecoder: Error on decoding frame.\n"); + return pag::DecodingResult::Error; + } + return static_cast( + env->CallIntMethod(videoDecoder.get(), GPUDecoder_onDecodeFrame)); } void GPUDecoder::onFlush() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return; - } - env->CallVoidMethod(videoDecoder.get(), GPUDecoder_onFlush); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + env->CallVoidMethod(videoDecoder.get(), GPUDecoder_onFlush); } int64_t GPUDecoder::presentationTime() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return -1; - } - return env->CallLongMethod(videoDecoder.get(), GPUDecoder_presentationTime); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return -1; + } + return env->CallLongMethod(videoDecoder.get(), GPUDecoder_presentationTime); } DecodingResult GPUDecoder::onEndOfStream() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - LOGE("GPUDecoder: Error on decoding frame.\n"); - return pag::DecodingResult::Error; - } - return static_cast( - env->CallIntMethod(videoDecoder.get(), GPUDecoder_onEndOfStream)); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + LOGE("GPUDecoder: Error on decoding frame.\n"); + return pag::DecodingResult::Error; + } + return static_cast( + env->CallIntMethod(videoDecoder.get(), GPUDecoder_onEndOfStream)); } std::shared_ptr GPUDecoder::onRenderFrame() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return nullptr; - } - videoSurface->updateTexImage(); - auto result = env->CallBooleanMethod(videoDecoder.get(), GPUDecoder_onRenderFrame); - if (!result) { - return nullptr; - } - return VideoImage::MakeFrom(videoSurface, videoWidth, videoHeight); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return nullptr; + } + videoSurface->updateTexImage(); + auto result = env->CallBooleanMethod(videoDecoder.get(), GPUDecoder_onRenderFrame); + if (!result) { + return nullptr; + } + return VideoImage::MakeFrom(videoSurface, videoWidth, videoHeight); } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/GPUDecoder.h b/src/platform/android/GPUDecoder.h index e58bd0d077..c62da094ed 100644 --- a/src/platform/android/GPUDecoder.h +++ b/src/platform/android/GPUDecoder.h @@ -25,36 +25,36 @@ namespace pag { class GPUDecoder : public VideoDecoder { - public: - static void InitJNI(JNIEnv* env, const std::string& className); +public: + static void InitJNI(JNIEnv* env, const std::string& className); - explicit GPUDecoder(const VideoConfig& config); + explicit GPUDecoder(const VideoConfig& config); - ~GPUDecoder() override; + ~GPUDecoder() override; - bool isValid() { - return _isValid; - } + bool isValid() { + return _isValid; + } - DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; + DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; - DecodingResult onEndOfStream() override; + DecodingResult onEndOfStream() override; - DecodingResult onDecodeFrame() override; + DecodingResult onDecodeFrame() override; - void onFlush() override; + void onFlush() override; - int64_t presentationTime() override; + int64_t presentationTime() override; - std::shared_ptr onRenderFrame() override; + std::shared_ptr onRenderFrame() override; - private: - bool _isValid = false; - int videoWidth = 0; - int videoHeight = 0; - std::shared_ptr videoSurface = nullptr; - Global videoDecoder; +private: + bool _isValid = false; + int videoWidth = 0; + int videoHeight = 0; + std::shared_ptr videoSurface = nullptr; + Global videoDecoder; - bool onConfigure(jobject decoder, const VideoConfig& config); + bool onConfigure(jobject decoder, const VideoConfig& config); }; } // namespace pag diff --git a/src/platform/android/GPUDrawable.cpp b/src/platform/android/GPUDrawable.cpp index e638023dbd..043110f73e 100644 --- a/src/platform/android/GPUDrawable.cpp +++ b/src/platform/android/GPUDrawable.cpp @@ -21,53 +21,53 @@ namespace pag { std::shared_ptr GPUDrawable::FromWindow(ANativeWindow* nativeWindow, - EGLContext sharedContext) { - if (nativeWindow == nullptr) { - LOGE("GPUDrawable.FromWindow() The nativeWindow is invalid."); - return nullptr; - } - return std::shared_ptr(new GPUDrawable(nativeWindow, sharedContext)); + EGLContext sharedContext) { + if (nativeWindow == nullptr) { + LOGE("GPUDrawable.FromWindow() The nativeWindow is invalid."); + return nullptr; + } + return std::shared_ptr(new GPUDrawable(nativeWindow, sharedContext)); } GPUDrawable::GPUDrawable(ANativeWindow* nativeWindow, EGLContext eglContext) : nativeWindow(nativeWindow), sharedContext(eglContext) { - updateSize(); + updateSize(); } GPUDrawable::~GPUDrawable() { - ANativeWindow_release(nativeWindow); + ANativeWindow_release(nativeWindow); } void GPUDrawable::updateSize() { - if (nativeWindow != nullptr) { - _width = ANativeWindow_getWidth(nativeWindow); - _height = ANativeWindow_getHeight(nativeWindow); - } + if (nativeWindow != nullptr) { + _width = ANativeWindow_getWidth(nativeWindow); + _height = ANativeWindow_getHeight(nativeWindow); + } } std::shared_ptr GPUDrawable::getDevice() { - if (_width <= 0 || _height <= 0) { - return nullptr; - } - if (window == nullptr) { - window = EGLWindow::MakeFrom(nativeWindow, sharedContext); - } - return window ? window->getDevice() : nullptr; + if (_width <= 0 || _height <= 0) { + return nullptr; + } + if (window == nullptr) { + window = EGLWindow::MakeFrom(nativeWindow, sharedContext); + } + return window ? window->getDevice() : nullptr; } std::shared_ptr GPUDrawable::createSurface(Context* context) { - return window ? window->createSurface(context) : nullptr; + return window ? window->createSurface(context) : nullptr; } void GPUDrawable::present(Context* context) { - if (window == nullptr) { - return; - } - return window->present(context, currentTimeStamp); + if (window == nullptr) { + return; + } + return window->present(context, currentTimeStamp); } void GPUDrawable::setTimeStamp(int64_t timeStamp) { - currentTimeStamp = timeStamp; + currentTimeStamp = timeStamp; } } // namespace pag diff --git a/src/platform/android/GPUDrawable.h b/src/platform/android/GPUDrawable.h index 8bfc0cc8df..f7b23084e9 100644 --- a/src/platform/android/GPUDrawable.h +++ b/src/platform/android/GPUDrawable.h @@ -25,38 +25,38 @@ namespace pag { class GPUDrawable : public Drawable { - public: - static std::shared_ptr FromWindow(ANativeWindow* nativeWindow, - EGLContext sharedContext = EGL_NO_CONTEXT); +public: + static std::shared_ptr FromWindow(ANativeWindow* nativeWindow, + EGLContext sharedContext = EGL_NO_CONTEXT); - ~GPUDrawable() override; + ~GPUDrawable() override; - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context* context) override; + void present(Context* context) override; - void setTimeStamp(int64_t timeStamp) override; + void setTimeStamp(int64_t timeStamp) override; - private: - int _width = 0; - int _height = 0; - ANativeWindow* nativeWindow = nullptr; - EGLContext sharedContext = nullptr; - int64_t currentTimeStamp = 0; - std::shared_ptr window = nullptr; +private: + int _width = 0; + int _height = 0; + ANativeWindow* nativeWindow = nullptr; + EGLContext sharedContext = nullptr; + int64_t currentTimeStamp = 0; + std::shared_ptr window = nullptr; - explicit GPUDrawable(ANativeWindow* nativeWindow, EGLContext eglContext = EGL_NO_CONTEXT); + explicit GPUDrawable(ANativeWindow* nativeWindow, EGLContext eglContext = EGL_NO_CONTEXT); }; } // namespace pag diff --git a/src/platform/android/Global.h b/src/platform/android/Global.h index 4184572280..c4582c07c7 100644 --- a/src/platform/android/Global.h +++ b/src/platform/android/Global.h @@ -22,46 +22,46 @@ template class Global { - public: - Global() : mEnv(nullptr), mRef(nullptr) { - } - - Global(JNIEnv* env, T ref) : mEnv(nullptr), mRef(nullptr) { - reset(env, ref); - } +public: + Global() : mEnv(nullptr), mRef(nullptr) { + } - ~Global() { - reset(nullptr, nullptr); - } + Global(JNIEnv* env, T ref) : mEnv(nullptr), mRef(nullptr) { + reset(env, ref); + } - void reset(JNIEnv* env, T ref) { - if (mRef == ref) { - return; + ~Global() { + reset(nullptr, nullptr); } - if (mRef != nullptr) { - if (env == nullptr) { - env = JNIEnvironment::Current(); - if (env == nullptr) { - return; + + void reset(JNIEnv* env, T ref) { + if (mRef == ref) { + return; } - } + if (mRef != nullptr) { + if (env == nullptr) { + env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + } - env->DeleteGlobalRef(mRef); - mRef = nullptr; - } - mEnv = env; - if (ref == nullptr) { - mRef = nullptr; - } else { - mRef = (T)mEnv->NewGlobalRef(ref); + env->DeleteGlobalRef(mRef); + mRef = nullptr; + } + mEnv = env; + if (ref == nullptr) { + mRef = nullptr; + } else { + mRef = (T)mEnv->NewGlobalRef(ref); + } } - } - T get() const { - return mRef; - } + T get() const { + return mRef; + } - private: - JNIEnv* mEnv; - T mRef; +private: + JNIEnv* mEnv; + T mRef; }; diff --git a/src/platform/android/JNIEnvironment.cpp b/src/platform/android/JNIEnvironment.cpp index 292570adaf..54ea25f772 100644 --- a/src/platform/android/JNIEnvironment.cpp +++ b/src/platform/android/JNIEnvironment.cpp @@ -23,41 +23,41 @@ static JavaVM* globalJavaVM = nullptr; static pthread_key_t threadKey = 0; static void JNI_Thread_Destroy(void* value) { - JNIEnv* jniEnv = (JNIEnv*)value; - if (jniEnv != nullptr && globalJavaVM != nullptr) { - globalJavaVM->DetachCurrentThread(); - pthread_setspecific(threadKey, nullptr); - } + JNIEnv* jniEnv = (JNIEnv*)value; + if (jniEnv != nullptr && globalJavaVM != nullptr) { + globalJavaVM->DetachCurrentThread(); + pthread_setspecific(threadKey, nullptr); + } } extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { - globalJavaVM = vm; + globalJavaVM = vm; - pthread_key_create(&threadKey, JNI_Thread_Destroy); + pthread_key_create(&threadKey, JNI_Thread_Destroy); - return JNI_VERSION_1_4; + return JNI_VERSION_1_4; } extern "C" void JNI_OnUnload(JavaVM*, void*) { - pthread_key_delete(threadKey); + pthread_key_delete(threadKey); } JNIEnv* JNIEnvironment::Current() { - if (globalJavaVM == nullptr) { - return nullptr; - } - JNIEnv* jniEnv = nullptr; - auto result = globalJavaVM->GetEnv(reinterpret_cast(&jniEnv), JNI_VERSION_1_4); - - if (result == JNI_EDETACHED || jniEnv == nullptr) { - JavaVMAttachArgs args = {JNI_VERSION_1_4, "PAG_JNIEnvironment", nullptr}; - if (globalJavaVM->AttachCurrentThread(&jniEnv, &args) != JNI_OK) { - return jniEnv; + if (globalJavaVM == nullptr) { + return nullptr; + } + JNIEnv* jniEnv = nullptr; + auto result = globalJavaVM->GetEnv(reinterpret_cast(&jniEnv), JNI_VERSION_1_4); + + if (result == JNI_EDETACHED || jniEnv == nullptr) { + JavaVMAttachArgs args = {JNI_VERSION_1_4, "PAG_JNIEnvironment", nullptr}; + if (globalJavaVM->AttachCurrentThread(&jniEnv, &args) != JNI_OK) { + return jniEnv; + } + pthread_setspecific(threadKey, (void*)jniEnv); + return jniEnv; + } else if (result == JNI_OK) { + return jniEnv; } - pthread_setspecific(threadKey, (void*)jniEnv); - return jniEnv; - } else if (result == JNI_OK) { return jniEnv; - } - return jniEnv; } diff --git a/src/platform/android/JNIEnvironment.h b/src/platform/android/JNIEnvironment.h index 8c25dad977..63a417b246 100644 --- a/src/platform/android/JNIEnvironment.h +++ b/src/platform/android/JNIEnvironment.h @@ -21,6 +21,6 @@ #include class JNIEnvironment { - public: - static JNIEnv* Current(); +public: + static JNIEnv* Current(); }; diff --git a/src/platform/android/JNIHelper.cpp b/src/platform/android/JNIHelper.cpp index 9eb3b4a3ae..e7592f2541 100644 --- a/src/platform/android/JNIHelper.cpp +++ b/src/platform/android/JNIHelper.cpp @@ -28,294 +28,294 @@ static constexpr int BITMAP_FLAGS_ALPHA_UNPREMUL = 2; static constexpr int BITMAP_FLAGS_IS_HARDWARE = 1 << 31; int JniThrowException(JNIEnv* env, const char* className, const char* msg) { - if (env->ExceptionCheck()) { - env->ExceptionClear(); - } - auto exceptionClass = env->FindClass(className); - if (exceptionClass == nullptr) { - return -1; - } - auto result = env->ThrowNew(exceptionClass, msg); - env->DeleteLocalRef(exceptionClass); - return result; + if (env->ExceptionCheck()) { + env->ExceptionClear(); + } + auto exceptionClass = env->FindClass(className); + if (exceptionClass == nullptr) { + return -1; + } + auto result = env->ThrowNew(exceptionClass, msg); + env->DeleteLocalRef(exceptionClass); + return result; } jobject MakeRectFObject(JNIEnv* env, float x, float y, float width, float height) { - static Global RectFClass(env, env->FindClass("android/graphics/RectF")); - static auto RectFConstructID = env->GetMethodID(RectFClass.get(), "", "(FFFF)V"); - return env->NewObject(RectFClass.get(), RectFConstructID, x, y, x + width, y + height); + static Global RectFClass(env, env->FindClass("android/graphics/RectF")); + static auto RectFConstructID = env->GetMethodID(RectFClass.get(), "", "(FFFF)V"); + return env->NewObject(RectFClass.get(), RectFConstructID, x, y, x + width, y + height); } jint MakeColorInt(JNIEnv*, uint32_t red, uint32_t green, uint32_t blue) { - uint32_t color = (255 << 24) | (red << 16) | (green << 8) | (blue << 0); - return static_cast(color); + uint32_t color = (255 << 24) | (red << 16) | (green << 8) | (blue << 0); + return static_cast(color); } jobject MakePAGFontObject(JNIEnv* env, const char* familyName, const char* familyStyle) { - static Global PAGFontClass(env, env->FindClass("org/libpag/PAGFont")); - static jmethodID PAGFontConstructID = env->GetMethodID(PAGFontClass.get(), "", "()V"); - static jfieldID PAGFont_fontFamily = - env->GetFieldID(PAGFontClass.get(), "fontFamily", "Ljava/lang/String;"); - static jfieldID PAGFont_fontStyle = - env->GetFieldID(PAGFontClass.get(), "fontStyle", "Ljava/lang/String;"); + static Global PAGFontClass(env, env->FindClass("org/libpag/PAGFont")); + static jmethodID PAGFontConstructID = env->GetMethodID(PAGFontClass.get(), "", "()V"); + static jfieldID PAGFont_fontFamily = + env->GetFieldID(PAGFontClass.get(), "fontFamily", "Ljava/lang/String;"); + static jfieldID PAGFont_fontStyle = + env->GetFieldID(PAGFontClass.get(), "fontStyle", "Ljava/lang/String;"); - jobject fontObject = env->NewObject(PAGFontClass.get(), PAGFontConstructID); - jstring fontFamily = SafeConvertToJString(env, familyName); - env->SetObjectField(fontObject, PAGFont_fontFamily, fontFamily); - env->DeleteLocalRef(fontFamily); - jstring fontStyle = SafeConvertToJString(env, familyStyle); - env->SetObjectField(fontObject, PAGFont_fontStyle, fontStyle); - env->DeleteLocalRef(fontStyle); - return fontObject; + jobject fontObject = env->NewObject(PAGFontClass.get(), PAGFontConstructID); + jstring fontFamily = SafeConvertToJString(env, familyName); + env->SetObjectField(fontObject, PAGFont_fontFamily, fontFamily); + env->DeleteLocalRef(fontFamily); + jstring fontStyle = SafeConvertToJString(env, familyStyle); + env->SetObjectField(fontObject, PAGFont_fontStyle, fontStyle); + env->DeleteLocalRef(fontStyle); + return fontObject; } jobject MakeByteBufferObject(JNIEnv* env, const void* bytes, size_t length) { - static Global ByteBufferClass(env, env->FindClass("java/nio/ByteBuffer")); - static jmethodID ByteBuffer_wrap = - env->GetStaticMethodID(ByteBufferClass.get(), "wrap", "([B)Ljava/nio/ByteBuffer;"); - jbyteArray byteArray = env->NewByteArray(length); - env->SetByteArrayRegion(byteArray, 0, length, (jbyte*)bytes); - auto result = env->CallStaticObjectMethod(ByteBufferClass.get(), ByteBuffer_wrap, byteArray); - env->DeleteLocalRef(byteArray); - return result; + static Global ByteBufferClass(env, env->FindClass("java/nio/ByteBuffer")); + static jmethodID ByteBuffer_wrap = + env->GetStaticMethodID(ByteBufferClass.get(), "wrap", "([B)Ljava/nio/ByteBuffer;"); + jbyteArray byteArray = env->NewByteArray(length); + env->SetByteArrayRegion(byteArray, 0, length, (jbyte*)bytes); + auto result = env->CallStaticObjectMethod(ByteBufferClass.get(), ByteBuffer_wrap, byteArray); + env->DeleteLocalRef(byteArray); + return result; } pag::Color ToColor(JNIEnv*, jint value) { - auto color = static_cast(value); - auto red = (((color) >> 16) & 0xFF); - auto green = (((color) >> 8) & 0xFF); - auto blue = (((color) >> 0) & 0xFF); - return {static_cast(red), static_cast(green), static_cast(blue)}; + auto color = static_cast(value); + auto red = (((color) >> 16) & 0xFF); + auto green = (((color) >> 8) & 0xFF); + auto blue = (((color) >> 0) & 0xFF); + return {static_cast(red), static_cast(green), static_cast(blue)}; } std::unique_ptr ReadBytesFromAssets(JNIEnv* env, jobject managerObj, - jstring pathObj) { - if (managerObj == nullptr || pathObj == nullptr) { - return nullptr; - } - auto manager = AAssetManager_fromJava(env, managerObj); - if (manager == nullptr) { - return nullptr; - } - auto path = SafeConvertToStdString(env, pathObj); - if (path.empty()) { - return nullptr; - } - auto asset = AAssetManager_open(manager, path.c_str(), AASSET_MODE_UNKNOWN); - if (asset == nullptr) { - return nullptr; - } - auto size = static_cast(AAsset_getLength(asset)); - auto byteData = pag::ByteData::Make(size); - auto numBytes = AAsset_read(asset, byteData->data(), size); - AAsset_close(asset); - if (numBytes <= 0) { - return nullptr; - } - return byteData; + jstring pathObj) { + if (managerObj == nullptr || pathObj == nullptr) { + return nullptr; + } + auto manager = AAssetManager_fromJava(env, managerObj); + if (manager == nullptr) { + return nullptr; + } + auto path = SafeConvertToStdString(env, pathObj); + if (path.empty()) { + return nullptr; + } + auto asset = AAssetManager_open(manager, path.c_str(), AASSET_MODE_UNKNOWN); + if (asset == nullptr) { + return nullptr; + } + auto size = static_cast(AAsset_getLength(asset)); + auto byteData = pag::ByteData::Make(size); + auto numBytes = AAsset_read(asset, byteData->data(), size); + AAsset_close(asset); + if (numBytes <= 0) { + return nullptr; + } + return byteData; } RectData ToRectData(JNIEnv* env, jobject rect) { - static Global RectFClass(env, env->FindClass("android/graphics/RectF")); - static auto leftID = env->GetFieldID(RectFClass.get(), "left", "F"); - static auto topID = env->GetFieldID(RectFClass.get(), "top", "F"); - static auto rightID = env->GetFieldID(RectFClass.get(), "right", "F"); - static auto bottomID = env->GetFieldID(RectFClass.get(), "bottom", "F"); - auto left = env->GetFloatField(rect, leftID); - auto top = env->GetFloatField(rect, topID); - auto right = env->GetFloatField(rect, rightID); - auto bottom = env->GetFloatField(rect, bottomID); - return {left, top, right - left, bottom - top}; + static Global RectFClass(env, env->FindClass("android/graphics/RectF")); + static auto leftID = env->GetFieldID(RectFClass.get(), "left", "F"); + static auto topID = env->GetFieldID(RectFClass.get(), "top", "F"); + static auto rightID = env->GetFieldID(RectFClass.get(), "right", "F"); + static auto bottomID = env->GetFieldID(RectFClass.get(), "bottom", "F"); + auto left = env->GetFloatField(rect, leftID); + auto top = env->GetFloatField(rect, topID); + auto right = env->GetFloatField(rect, rightID); + auto bottom = env->GetFloatField(rect, bottomID); + return {left, top, right - left, bottom - top}; } jobjectArray ToPAGLayerJavaObjectList(JNIEnv* env, const std::vector>& layers) { - static Global PAGLayer_Class(env, env->FindClass("org/libpag/PAGLayer")); - if (layers.empty()) { - return env->NewObjectArray(0, PAGLayer_Class.get(), nullptr); - } - jobjectArray layerArray = env->NewObjectArray(layers.size(), PAGLayer_Class.get(), nullptr); - for (size_t i = 0; i < layers.size(); ++i) { - auto layer = layers[i]; - auto jLayer = ToPAGLayerJavaObject(env, layer); - env->SetObjectArrayElement(layerArray, i, jLayer); - } - return layerArray; + static Global PAGLayer_Class(env, env->FindClass("org/libpag/PAGLayer")); + if (layers.empty()) { + return env->NewObjectArray(0, PAGLayer_Class.get(), nullptr); + } + jobjectArray layerArray = env->NewObjectArray(layers.size(), PAGLayer_Class.get(), nullptr); + for (size_t i = 0; i < layers.size(); ++i) { + auto layer = layers[i]; + auto jLayer = ToPAGLayerJavaObject(env, layer); + env->SetObjectArrayElement(layerArray, i, jLayer); + } + return layerArray; } jobject ToPAGLayerJavaObject(JNIEnv* env, std::shared_ptr pagLayer) { - if (env == nullptr || pagLayer == nullptr) { - return nullptr; - } - if (pagLayer->externalHandle != nullptr && - !env->IsSameObject(static_cast(pagLayer->externalHandle), nullptr)) { - return static_cast(pagLayer->externalHandle); - } - jobject layerObject = nullptr; - switch (pagLayer->layerType()) { - case pag::LayerType::Shape: { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGShapeLayer")); - static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); - layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, - reinterpret_cast(new JPAGLayerHandle(pagLayer))); - break; + if (env == nullptr || pagLayer == nullptr) { + return nullptr; } - case pag::LayerType::Solid: { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGSolidLayer")); - static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); - layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, - reinterpret_cast(new JPAGLayerHandle(pagLayer))); - break; + if (pagLayer->externalHandle != nullptr && + !env->IsSameObject(static_cast(pagLayer->externalHandle), nullptr)) { + return static_cast(pagLayer->externalHandle); } - case pag::LayerType::PreCompose: { - if (std::static_pointer_cast(pagLayer)->isPAGFile()) { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGFile")); + jobject layerObject = nullptr; + switch (pagLayer->layerType()) { + case pag::LayerType::Shape: { + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGShapeLayer")); static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, reinterpret_cast(new JPAGLayerHandle(pagLayer))); - } else { - static auto PAGLayer_Class = - Global(env, env->FindClass("org/libpag/PAGComposition")); + break; + } + case pag::LayerType::Solid: { + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGSolidLayer")); static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, reinterpret_cast(new JPAGLayerHandle(pagLayer))); - } + break; + } + case pag::LayerType::PreCompose: { + if (std::static_pointer_cast(pagLayer)->isPAGFile()) { + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGFile")); + static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); + layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, + reinterpret_cast(new JPAGLayerHandle(pagLayer))); + } else { + static auto PAGLayer_Class = + Global(env, env->FindClass("org/libpag/PAGComposition")); + static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); + layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, + reinterpret_cast(new JPAGLayerHandle(pagLayer))); + } - break; + break; } case pag::LayerType::Text: { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGTextLayer")); - static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); - layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, - reinterpret_cast(new JPAGLayerHandle(pagLayer))); - break; + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGTextLayer")); + static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); + layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, + reinterpret_cast(new JPAGLayerHandle(pagLayer))); + break; } case pag::LayerType::Image: { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGImageLayer")); - static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); - layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, - reinterpret_cast(new JPAGLayerHandle(pagLayer))); - break; + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGImageLayer")); + static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); + layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, + reinterpret_cast(new JPAGLayerHandle(pagLayer))); + break; } default: { - static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGLayer")); - static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); - layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, - reinterpret_cast(new JPAGLayerHandle(pagLayer))); - break; + static auto PAGLayer_Class = Global(env, env->FindClass("org/libpag/PAGLayer")); + static auto PAGLayer_Constructor = env->GetMethodID(PAGLayer_Class.get(), "", "(J)V"); + layerObject = env->NewObject(PAGLayer_Class.get(), PAGLayer_Constructor, + reinterpret_cast(new JPAGLayerHandle(pagLayer))); + break; + } } - } - auto gObject = env->NewWeakGlobalRef(layerObject); - pagLayer->externalHandle = gObject; - env->DeleteLocalRef(layerObject); - return gObject; + auto gObject = env->NewWeakGlobalRef(layerObject); + pagLayer->externalHandle = gObject; + env->DeleteLocalRef(layerObject); + return gObject; } std::shared_ptr ToPAGLayerNativeObject(JNIEnv* env, jobject jLayer) { - if (env == nullptr || jLayer == nullptr) { - return nullptr; - } + if (env == nullptr || jLayer == nullptr) { + return nullptr; + } - static Global PAGLayer_Class(env, env->FindClass("org/libpag/PAGLayer")); - static auto PAGLayer_nativeContext = env->GetFieldID(PAGLayer_Class.get(), "nativeContext", "J"); + static Global PAGLayer_Class(env, env->FindClass("org/libpag/PAGLayer")); + static auto PAGLayer_nativeContext = env->GetFieldID(PAGLayer_Class.get(), "nativeContext", "J"); - auto nativeContext = - reinterpret_cast(env->GetLongField(jLayer, PAGLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } + auto nativeContext = + reinterpret_cast(env->GetLongField(jLayer, PAGLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } - return nativeContext->get(); + return nativeContext->get(); } std::shared_ptr ToPAGCompositionNativeObject(JNIEnv* env, - jobject jComposition) { - if (env == nullptr || jComposition == nullptr) { - return nullptr; - } + jobject jComposition) { + if (env == nullptr || jComposition == nullptr) { + return nullptr; + } - static Global PAGComposition_Class(env, env->FindClass("org/libpag/PAGComposition")); - static auto PAGComposition_nativeContext = - env->GetFieldID(PAGComposition_Class.get(), "nativeContext", "J"); + static Global PAGComposition_Class(env, env->FindClass("org/libpag/PAGComposition")); + static auto PAGComposition_nativeContext = + env->GetFieldID(PAGComposition_Class.get(), "nativeContext", "J"); - auto nativeContext = reinterpret_cast( - env->GetLongField(jComposition, PAGComposition_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } + auto nativeContext = reinterpret_cast( + env->GetLongField(jComposition, PAGComposition_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } - return std::static_pointer_cast(nativeContext->get()); + return std::static_pointer_cast(nativeContext->get()); } jobject ToPAGMarkerObject(JNIEnv* env, const pag::Marker* marker) { - if (env == nullptr || marker == nullptr) { - return nullptr; - } + if (env == nullptr || marker == nullptr) { + return nullptr; + } - static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); - static auto PAGMarker_Construct = - env->GetMethodID(PAGMarker_Class.get(), "", "(JJLjava/lang/String;)V"); - jstring comment = SafeConvertToJString(env, marker->comment.c_str()); - auto result = env->NewObject(PAGMarker_Class.get(), PAGMarker_Construct, marker->startTime, - marker->duration, comment); - env->DeleteLocalRef(comment); - return result; + static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); + static auto PAGMarker_Construct = + env->GetMethodID(PAGMarker_Class.get(), "", "(JJLjava/lang/String;)V"); + jstring comment = SafeConvertToJString(env, marker->comment.c_str()); + auto result = env->NewObject(PAGMarker_Class.get(), PAGMarker_Construct, marker->startTime, + marker->duration, comment); + env->DeleteLocalRef(comment); + return result; } jobject ToPAGVideoRangeObject(JNIEnv* env, const pag::PAGVideoRange& range) { - if (env == nullptr) { - return nullptr; - } + if (env == nullptr) { + return nullptr; + } - static Global PAGVideoRange_Class(env, env->FindClass("org/libpag/PAGVideoRange")); - static auto PAGVideoRange_Construct = - env->GetMethodID(PAGVideoRange_Class.get(), "", "(JJJZ)V"); - return env->NewObject(PAGVideoRange_Class.get(), PAGVideoRange_Construct, range.startTime(), - range.endTime(), range.playDuration(), range.reversed()); + static Global PAGVideoRange_Class(env, env->FindClass("org/libpag/PAGVideoRange")); + static auto PAGVideoRange_Construct = + env->GetMethodID(PAGVideoRange_Class.get(), "", "(JJJZ)V"); + return env->NewObject(PAGVideoRange_Class.get(), PAGVideoRange_Construct, range.startTime(), + range.endTime(), range.playDuration(), range.reversed()); } jobject ToHashMapObject(JNIEnv* env, std::unordered_map map) { - if (env == nullptr) { - return nullptr; - } - static Global HashMap_Class(env, env->FindClass("java/util/HashMap")); - static auto HashMap_Construct = env->GetMethodID(HashMap_Class.get(), "", "()V"); - static jmethodID HashMap_put = env->GetMethodID( - HashMap_Class.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - auto jMap = env->NewObject(HashMap_Class.get(), HashMap_Construct, ""); - if (!map.empty()) { - for (auto& item : map) { - auto key = SafeConvertToJString(env, item.first.c_str()); - auto value = SafeConvertToJString(env, item.second.c_str()); - env->CallObjectMethod(jMap, HashMap_put, key, value); - env->DeleteLocalRef(key); - env->DeleteLocalRef(value); + if (env == nullptr) { + return nullptr; + } + static Global HashMap_Class(env, env->FindClass("java/util/HashMap")); + static auto HashMap_Construct = env->GetMethodID(HashMap_Class.get(), "", "()V"); + static jmethodID HashMap_put = env->GetMethodID( + HashMap_Class.get(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + auto jMap = env->NewObject(HashMap_Class.get(), HashMap_Construct, ""); + if (!map.empty()) { + for (auto& item : map) { + auto key = SafeConvertToJString(env, item.first.c_str()); + auto value = SafeConvertToJString(env, item.second.c_str()); + env->CallObjectMethod(jMap, HashMap_put, key, value); + env->DeleteLocalRef(key); + env->DeleteLocalRef(value); + } } - } - return jMap; + return jMap; } pag::ImageInfo GetImageInfo(JNIEnv* env, jobject bitmap) { - AndroidBitmapInfo bitmapInfo = {}; - if (bitmap == nullptr || AndroidBitmap_getInfo(env, bitmap, &bitmapInfo) != 0 || - (bitmapInfo.flags & BITMAP_FLAGS_IS_HARDWARE)) { - return {}; - } - pag::AlphaType alphaType = (bitmapInfo.flags & BITMAP_FLAGS_ALPHA_UNPREMUL) - ? pag::AlphaType::Unpremultiplied - : pag::AlphaType::Premultiplied; - pag::ColorType colorType; - switch (bitmapInfo.format) { + AndroidBitmapInfo bitmapInfo = {}; + if (bitmap == nullptr || AndroidBitmap_getInfo(env, bitmap, &bitmapInfo) != 0 || + (bitmapInfo.flags & BITMAP_FLAGS_IS_HARDWARE)) { + return {}; + } + pag::AlphaType alphaType = (bitmapInfo.flags & BITMAP_FLAGS_ALPHA_UNPREMUL) + ? pag::AlphaType::Unpremultiplied + : pag::AlphaType::Premultiplied; + pag::ColorType colorType; + switch (bitmapInfo.format) { case ANDROID_BITMAP_FORMAT_RGBA_8888: - colorType = pag::ColorType::RGBA_8888; - break; + colorType = pag::ColorType::RGBA_8888; + break; case ANDROID_BITMAP_FORMAT_A_8: - colorType = pag::ColorType::ALPHA_8; - break; + colorType = pag::ColorType::ALPHA_8; + break; default: - colorType = pag::ColorType::Unknown; - break; - } - return pag::ImageInfo::Make(bitmapInfo.width, bitmapInfo.height, colorType, alphaType, - bitmapInfo.stride); + colorType = pag::ColorType::Unknown; + break; + } + return pag::ImageInfo::Make(bitmapInfo.width, bitmapInfo.height, colorType, alphaType, + bitmapInfo.stride); } \ No newline at end of file diff --git a/src/platform/android/JNIHelper.h b/src/platform/android/JNIHelper.h index d632b3d75c..0c0d7df5f2 100644 --- a/src/platform/android/JNIHelper.h +++ b/src/platform/android/JNIHelper.h @@ -27,7 +27,7 @@ #include "platform/android/JStringUtil.h" struct RectData { - float x, y, width, height; + float x, y, width, height; }; int JniThrowException(JNIEnv* env, const char* className, const char* msg); @@ -45,7 +45,7 @@ pag::Color ToColor(JNIEnv* env, jint color); RectData ToRectData(JNIEnv* env, jobject rect); std::unique_ptr ReadBytesFromAssets(JNIEnv* env, jobject managerObj, - jstring pathObj); + jstring pathObj); jobjectArray ToPAGLayerJavaObjectList(JNIEnv* env, const std::vector>& layers); @@ -55,7 +55,7 @@ jobject ToPAGLayerJavaObject(JNIEnv* env, std::shared_ptr pagLaye std::shared_ptr ToPAGLayerNativeObject(JNIEnv* env, jobject jLayer); std::shared_ptr ToPAGCompositionNativeObject(JNIEnv* env, - jobject jComposition); + jobject jComposition); jobject ToPAGMarkerObject(JNIEnv* env, const pag::Marker* marker); diff --git a/src/platform/android/JPAG.cpp b/src/platform/android/JPAG.cpp index 171c525cd6..df82ad1ece 100644 --- a/src/platform/android/JPAG.cpp +++ b/src/platform/android/JPAG.cpp @@ -20,5 +20,5 @@ #include "pag/pag.h" extern "C" JNIEXPORT jstring JNICALL Java_org_libpag_PAG_SDKVersion(JNIEnv* env, jclass) { - return SafeConvertToJString(env, pag::PAG::SDKVersion().c_str()); + return SafeConvertToJString(env, pag::PAG::SDKVersion().c_str()); } diff --git a/src/platform/android/JPAGComposition.cpp b/src/platform/android/JPAGComposition.cpp index 8b4de7291f..8fdda8c1b0 100644 --- a/src/platform/android/JPAGComposition.cpp +++ b/src/platform/android/JPAGComposition.cpp @@ -24,254 +24,254 @@ static jfieldID PAGComposition_nativeContext; using namespace pag; std::shared_ptr GetPAGComposition(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGComposition_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGComposition_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGComposition_nativeInit(JNIEnv* env, jclass clazz) { - PAGComposition_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} - -JNIEXPORT jobject Java_org_libpag_PAGComposition_Make(JNIEnv* env, jclass, jint width, - jint height) { - auto composition = PAGComposition::Make(width, height); - if (composition == nullptr) { - return nullptr; - } - return ToPAGLayerJavaObject(env, composition); -} - -JNIEXPORT jint Java_org_libpag_PAGComposition_width(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return 0; - } - return composition->width(); -} - -JNIEXPORT jint Java_org_libpag_PAGComposition_height(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return 0; - } - return composition->height(); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_setContentSize(JNIEnv* env, jobject thiz, jint width, - jint height) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - composition->setContentSize(width, height); -} - -JNIEXPORT jint Java_org_libpag_PAGComposition_numChildren(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return 0; - } - - return composition->numChildren(); -} - -JNIEXPORT jobject Java_org_libpag_PAGComposition_getLayerAt(JNIEnv* env, jobject thiz, jint index) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return nullptr; - } - - auto pagLayer = composition->getLayerAt(index); - if (pagLayer == nullptr) { - return nullptr; - } - - return ToPAGLayerJavaObject(env, pagLayer); -} - -JNIEXPORT jint Java_org_libpag_PAGComposition_getLayerIndex(JNIEnv* env, jobject thiz, - jobject layer) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return -1; - } - - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return -1; - } - - return composition->getLayerIndex(pagLayer); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_setLayerIndex(JNIEnv* env, jobject thiz, - jobject layer, jint index) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return; - } - - composition->setLayerIndex(pagLayer, index); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_addLayer(JNIEnv* env, jobject thiz, jobject layer) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return; - } - composition->addLayer(pagLayer); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_addLayerAt(JNIEnv* env, jobject thiz, jobject layer, - jint index) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return; - } - composition->addLayerAt(pagLayer, index); -} - -JNIEXPORT jboolean Java_org_libpag_PAGComposition_contains(JNIEnv* env, jobject thiz, - jobject layer) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return JNI_FALSE; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return JNI_FALSE; - } - return (jboolean)composition->contains(pagLayer); -} - -JNIEXPORT jobject Java_org_libpag_PAGComposition_removeLayer(JNIEnv* env, jobject thiz, - jobject layer) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return nullptr; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - if (pagLayer == nullptr) { - return nullptr; - } - return ToPAGLayerJavaObject(env, composition->removeLayer(pagLayer)); -} - -JNIEXPORT jobject Java_org_libpag_PAGComposition_removeLayerAt(JNIEnv* env, jobject thiz, - jint index) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return nullptr; - } - return ToPAGLayerJavaObject(env, composition->removeLayerAt(index)); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_removeAllLayers(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - composition->removeAllLayers(); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_swapLayer(JNIEnv* env, jobject thiz, jobject layer1, - jobject layer2) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - auto pagLayer1 = ToPAGLayerNativeObject(env, layer1); - if (pagLayer1 == nullptr) { - return; - } - auto pagLayer2 = ToPAGLayerNativeObject(env, layer2); - if (pagLayer1 == nullptr) { - return; - } - composition->swapLayer(pagLayer1, pagLayer2); -} - -JNIEXPORT void Java_org_libpag_PAGComposition_swapLayerAt(JNIEnv* env, jobject thiz, jint index1, - jint index2) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return; - } - composition->swapLayerAt(index1, index2); -} - -JNIEXPORT jobject Java_org_libpag_PAGComposition_audioBytes(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr || composition->audioBytes() == nullptr) { - return nullptr; - } - return env->NewDirectByteBuffer(composition->audioBytes()->data(), - composition->audioBytes()->length()); -} - -JNIEXPORT jlong Java_org_libpag_PAGComposition_audioStartTime(JNIEnv* env, jobject thiz) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return 0; - } - - return composition->audioStartTime(); -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_audioMarkers(JNIEnv* env, jobject thiz) { - static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr || composition->audioMarkers().empty()) { - return env->NewObjectArray(0, PAGMarker_Class.get(), nullptr); - } - int markerSize = composition->audioMarkers().size(); - jobjectArray markerArray = env->NewObjectArray(markerSize, PAGMarker_Class.get(), nullptr); - for (int i = 0; i < markerSize; ++i) { - jobject jMarker = ToPAGMarkerObject(env, composition->audioMarkers()[i]); - env->SetObjectArrayElement(markerArray, i, jMarker); - env->DeleteLocalRef(jMarker); - } - return markerArray; -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_getLayersByName(JNIEnv* env, jobject thiz, - jstring layerName) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return ToPAGLayerJavaObjectList(env, {}); - } - auto name = SafeConvertToStdString(env, layerName); - auto layers = composition->getLayersByName(name); - return ToPAGLayerJavaObjectList(env, layers); -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_getLayersUnderPoint(JNIEnv* env, jobject thiz, - jfloat localX, - jfloat localY) { - auto composition = GetPAGComposition(env, thiz); - if (composition == nullptr) { - return ToPAGLayerJavaObjectList(env, {}); - } - auto layers = composition->getLayersUnderPoint(localX, localY); - return ToPAGLayerJavaObjectList(env, layers); -} + JNIEXPORT void Java_org_libpag_PAGComposition_nativeInit(JNIEnv* env, jclass clazz) { + PAGComposition_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } + + JNIEXPORT jobject Java_org_libpag_PAGComposition_Make(JNIEnv* env, jclass, jint width, + jint height) { + auto composition = PAGComposition::Make(width, height); + if (composition == nullptr) { + return nullptr; + } + return ToPAGLayerJavaObject(env, composition); + } + + JNIEXPORT jint Java_org_libpag_PAGComposition_width(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return 0; + } + return composition->width(); + } + + JNIEXPORT jint Java_org_libpag_PAGComposition_height(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return 0; + } + return composition->height(); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_setContentSize(JNIEnv* env, jobject thiz, jint width, + jint height) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + composition->setContentSize(width, height); + } + + JNIEXPORT jint Java_org_libpag_PAGComposition_numChildren(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return 0; + } + + return composition->numChildren(); + } + + JNIEXPORT jobject Java_org_libpag_PAGComposition_getLayerAt(JNIEnv* env, jobject thiz, jint index) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return nullptr; + } + + auto pagLayer = composition->getLayerAt(index); + if (pagLayer == nullptr) { + return nullptr; + } + + return ToPAGLayerJavaObject(env, pagLayer); + } + + JNIEXPORT jint Java_org_libpag_PAGComposition_getLayerIndex(JNIEnv* env, jobject thiz, + jobject layer) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return -1; + } + + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return -1; + } + + return composition->getLayerIndex(pagLayer); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_setLayerIndex(JNIEnv* env, jobject thiz, + jobject layer, jint index) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return; + } + + composition->setLayerIndex(pagLayer, index); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_addLayer(JNIEnv* env, jobject thiz, jobject layer) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return; + } + composition->addLayer(pagLayer); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_addLayerAt(JNIEnv* env, jobject thiz, jobject layer, + jint index) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return; + } + composition->addLayerAt(pagLayer, index); + } + + JNIEXPORT jboolean Java_org_libpag_PAGComposition_contains(JNIEnv* env, jobject thiz, + jobject layer) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return JNI_FALSE; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return JNI_FALSE; + } + return (jboolean)composition->contains(pagLayer); + } + + JNIEXPORT jobject Java_org_libpag_PAGComposition_removeLayer(JNIEnv* env, jobject thiz, + jobject layer) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return nullptr; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + if (pagLayer == nullptr) { + return nullptr; + } + return ToPAGLayerJavaObject(env, composition->removeLayer(pagLayer)); + } + + JNIEXPORT jobject Java_org_libpag_PAGComposition_removeLayerAt(JNIEnv* env, jobject thiz, + jint index) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return nullptr; + } + return ToPAGLayerJavaObject(env, composition->removeLayerAt(index)); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_removeAllLayers(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + composition->removeAllLayers(); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_swapLayer(JNIEnv* env, jobject thiz, jobject layer1, + jobject layer2) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + auto pagLayer1 = ToPAGLayerNativeObject(env, layer1); + if (pagLayer1 == nullptr) { + return; + } + auto pagLayer2 = ToPAGLayerNativeObject(env, layer2); + if (pagLayer1 == nullptr) { + return; + } + composition->swapLayer(pagLayer1, pagLayer2); + } + + JNIEXPORT void Java_org_libpag_PAGComposition_swapLayerAt(JNIEnv* env, jobject thiz, jint index1, + jint index2) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return; + } + composition->swapLayerAt(index1, index2); + } + + JNIEXPORT jobject Java_org_libpag_PAGComposition_audioBytes(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr || composition->audioBytes() == nullptr) { + return nullptr; + } + return env->NewDirectByteBuffer(composition->audioBytes()->data(), + composition->audioBytes()->length()); + } + + JNIEXPORT jlong Java_org_libpag_PAGComposition_audioStartTime(JNIEnv* env, jobject thiz) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return 0; + } + + return composition->audioStartTime(); + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_audioMarkers(JNIEnv* env, jobject thiz) { + static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr || composition->audioMarkers().empty()) { + return env->NewObjectArray(0, PAGMarker_Class.get(), nullptr); + } + int markerSize = composition->audioMarkers().size(); + jobjectArray markerArray = env->NewObjectArray(markerSize, PAGMarker_Class.get(), nullptr); + for (int i = 0; i < markerSize; ++i) { + jobject jMarker = ToPAGMarkerObject(env, composition->audioMarkers()[i]); + env->SetObjectArrayElement(markerArray, i, jMarker); + env->DeleteLocalRef(jMarker); + } + return markerArray; + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_getLayersByName(JNIEnv* env, jobject thiz, + jstring layerName) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return ToPAGLayerJavaObjectList(env, {}); + } + auto name = SafeConvertToStdString(env, layerName); + auto layers = composition->getLayersByName(name); + return ToPAGLayerJavaObjectList(env, layers); + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGComposition_getLayersUnderPoint(JNIEnv* env, jobject thiz, + jfloat localX, + jfloat localY) { + auto composition = GetPAGComposition(env, thiz); + if (composition == nullptr) { + return ToPAGLayerJavaObjectList(env, {}); + } + auto layers = composition->getLayersUnderPoint(localX, localY); + return ToPAGLayerJavaObjectList(env, layers); + } } \ No newline at end of file diff --git a/src/platform/android/JPAGFile.cpp b/src/platform/android/JPAGFile.cpp index 656b3e88f1..bc5d6c44e7 100644 --- a/src/platform/android/JPAGFile.cpp +++ b/src/platform/android/JPAGFile.cpp @@ -29,194 +29,194 @@ static jfieldID PAGFile_nativeContext; using namespace pag; std::shared_ptr getPAGFile(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGFile_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGFile_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGFile_nativeInit(JNIEnv* env, jclass clazz) { - PAGFile_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); - // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass - // 可能会失败,因此要提前初始化这部分反射方法。 - NativePlatform::InitJNI(env); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_MaxSupportedTagLevel(JNIEnv*, jclass) { - return pag::PAGFile::MaxSupportedTagLevel(); -} - -JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromPath(JNIEnv* env, jclass, jstring pathObj) { - if (pathObj == nullptr) { - LOGE("PAGFile.LoadFromPath() Invalid path specified."); - return NULL; - } - auto path = SafeConvertToStdString(env, pathObj); - if (path.empty()) { - return NULL; - } - LOGI("PAGFile.LoadFromPath() start: %s", path.c_str()); - auto pagFile = PAGFile::Load(path); - if (pagFile == nullptr) { - LOGE("PAGFile.LoadFromPath() Invalid pag file : %s", path.c_str()); - return NULL; - } - return ToPAGLayerJavaObject(env, pagFile); -} - -JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromBytes(JNIEnv* env, jclass, jbyteArray bytes, - jint length) { - if (bytes == nullptr) { - LOGE("PAGFile.LoadFromBytes() Invalid image bytes specified."); - return NULL; - } - auto data = env->GetByteArrayElements(bytes, nullptr); - auto pagFile = PAGFile::Load(data, static_cast(length)); - env->ReleaseByteArrayElements(bytes, data, 0); - if (pagFile == nullptr) { - LOGE("PAGFile.LoadFromBytes() Invalid image bytes specified."); - return NULL; - } - return ToPAGLayerJavaObject(env, pagFile); -} - -JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromAssets(JNIEnv* env, jclass, jobject managerObj, - jstring pathObj) { - auto path = SafeConvertToStdString(env, pathObj); - auto byteData = ReadBytesFromAssets(env, managerObj, pathObj); - if (byteData == nullptr) { - LOGE("PAGFile.LoadFromAssets() Can't find the file name from asset manager : %s", path.c_str()); - return NULL; - } - LOGI("PAGFile.LoadFromAssets() start: %s", path.c_str()); - auto pagFile = PAGFile::Load(byteData->data(), byteData->length(), "assets://" + path); - if (pagFile == nullptr) { - LOGE("PAGFile.LoadFromAssets() Invalid pag file : %s", path.c_str()); - return NULL; - } - return ToPAGLayerJavaObject(env, pagFile); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_tagLevel(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - return pagFile->tagLevel(); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_numTexts(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - return pagFile->numTexts(); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_numImages(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - return pagFile->numImages(); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_numVideos(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - return pagFile->numVideos(); -} - -JNIEXPORT jstring Java_org_libpag_PAGFile_path(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - auto path = pagFile->path(); - return SafeConvertToJString(env, path.c_str()); -} - -JNIEXPORT jobject Java_org_libpag_PAGFile_getTextData(JNIEnv* env, jobject thiz, jint index) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return nullptr; - } - auto textDocument = pagFile->getTextData(index); - return ToPAGTextObject(env, textDocument); -} - -JNIEXPORT void Java_org_libpag_PAGFile_replaceText(JNIEnv* env, jobject thiz, jint index, - jobject textData) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return; - } - auto textDocument = ToTextDocument(env, textData); - pagFile->replaceText(index, textDocument); -} - -JNIEXPORT void Java_org_libpag_PAGFile_nativeReplaceImage(JNIEnv* env, jobject thiz, jint index, - jlong imageObject) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return; - } - auto image = reinterpret_cast(imageObject); - if (image != nullptr) { - pagFile->replaceImage(index, image->get()); - } else { - pagFile->replaceImage(index, nullptr); - } -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGFile_getLayersByEditableIndex(JNIEnv* env, jobject thiz, - jint editableIndex, - jint layerType) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return ToPAGLayerJavaObjectList(env, {}); - } - auto layers = - pagFile->getLayersByEditableIndex(editableIndex, static_cast(layerType)); - return ToPAGLayerJavaObjectList(env, layers); -} - -JNIEXPORT jint Java_org_libpag_PAGFile_timeStretchMode(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return 0; - } - return pagFile->timeStretchMode(); -} - -JNIEXPORT void Java_org_libpag_PAGFile_setTimeStretchMode(JNIEnv* env, jobject thiz, jint mode) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return; - } - pagFile->setTimeStretchMode(static_cast(mode)); -} - -JNIEXPORT void Java_org_libpag_PAGFile_setDuration(JNIEnv* env, jobject thiz, jlong duration) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return; - } - pagFile->setDuration(duration); -} - -JNIEXPORT jobject Java_org_libpag_PAGFile_copyOriginal(JNIEnv* env, jobject thiz) { - auto pagFile = getPAGFile(env, thiz); - if (pagFile == nullptr) { - return NULL; - } - auto newFile = pagFile->copyOriginal(); - return ToPAGLayerJavaObject(env, newFile); -} + JNIEXPORT void Java_org_libpag_PAGFile_nativeInit(JNIEnv* env, jclass clazz) { + PAGFile_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass + // 可能会失败,因此要提前初始化这部分反射方法。 + NativePlatform::InitJNI(env); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_MaxSupportedTagLevel(JNIEnv*, jclass) { + return pag::PAGFile::MaxSupportedTagLevel(); + } + + JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromPath(JNIEnv* env, jclass, jstring pathObj) { + if (pathObj == nullptr) { + LOGE("PAGFile.LoadFromPath() Invalid path specified."); + return NULL; + } + auto path = SafeConvertToStdString(env, pathObj); + if (path.empty()) { + return NULL; + } + LOGI("PAGFile.LoadFromPath() start: %s", path.c_str()); + auto pagFile = PAGFile::Load(path); + if (pagFile == nullptr) { + LOGE("PAGFile.LoadFromPath() Invalid pag file : %s", path.c_str()); + return NULL; + } + return ToPAGLayerJavaObject(env, pagFile); + } + + JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromBytes(JNIEnv* env, jclass, jbyteArray bytes, + jint length) { + if (bytes == nullptr) { + LOGE("PAGFile.LoadFromBytes() Invalid image bytes specified."); + return NULL; + } + auto data = env->GetByteArrayElements(bytes, nullptr); + auto pagFile = PAGFile::Load(data, static_cast(length)); + env->ReleaseByteArrayElements(bytes, data, 0); + if (pagFile == nullptr) { + LOGE("PAGFile.LoadFromBytes() Invalid image bytes specified."); + return NULL; + } + return ToPAGLayerJavaObject(env, pagFile); + } + + JNIEXPORT jobject Java_org_libpag_PAGFile_LoadFromAssets(JNIEnv* env, jclass, jobject managerObj, + jstring pathObj) { + auto path = SafeConvertToStdString(env, pathObj); + auto byteData = ReadBytesFromAssets(env, managerObj, pathObj); + if (byteData == nullptr) { + LOGE("PAGFile.LoadFromAssets() Can't find the file name from asset manager : %s", path.c_str()); + return NULL; + } + LOGI("PAGFile.LoadFromAssets() start: %s", path.c_str()); + auto pagFile = PAGFile::Load(byteData->data(), byteData->length(), "assets://" + path); + if (pagFile == nullptr) { + LOGE("PAGFile.LoadFromAssets() Invalid pag file : %s", path.c_str()); + return NULL; + } + return ToPAGLayerJavaObject(env, pagFile); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_tagLevel(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + return pagFile->tagLevel(); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_numTexts(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numTexts(); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_numImages(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numImages(); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_numVideos(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + return pagFile->numVideos(); + } + + JNIEXPORT jstring Java_org_libpag_PAGFile_path(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + auto path = pagFile->path(); + return SafeConvertToJString(env, path.c_str()); + } + + JNIEXPORT jobject Java_org_libpag_PAGFile_getTextData(JNIEnv* env, jobject thiz, jint index) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return nullptr; + } + auto textDocument = pagFile->getTextData(index); + return ToPAGTextObject(env, textDocument); + } + + JNIEXPORT void Java_org_libpag_PAGFile_replaceText(JNIEnv* env, jobject thiz, jint index, + jobject textData) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return; + } + auto textDocument = ToTextDocument(env, textData); + pagFile->replaceText(index, textDocument); + } + + JNIEXPORT void Java_org_libpag_PAGFile_nativeReplaceImage(JNIEnv* env, jobject thiz, jint index, + jlong imageObject) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return; + } + auto image = reinterpret_cast(imageObject); + if (image != nullptr) { + pagFile->replaceImage(index, image->get()); + } else { + pagFile->replaceImage(index, nullptr); + } + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGFile_getLayersByEditableIndex(JNIEnv* env, jobject thiz, + jint editableIndex, + jint layerType) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return ToPAGLayerJavaObjectList(env, {}); + } + auto layers = + pagFile->getLayersByEditableIndex(editableIndex, static_cast(layerType)); + return ToPAGLayerJavaObjectList(env, layers); + } + + JNIEXPORT jint Java_org_libpag_PAGFile_timeStretchMode(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return 0; + } + return pagFile->timeStretchMode(); + } + + JNIEXPORT void Java_org_libpag_PAGFile_setTimeStretchMode(JNIEnv* env, jobject thiz, jint mode) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return; + } + pagFile->setTimeStretchMode(static_cast(mode)); + } + + JNIEXPORT void Java_org_libpag_PAGFile_setDuration(JNIEnv* env, jobject thiz, jlong duration) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return; + } + pagFile->setDuration(duration); + } + + JNIEXPORT jobject Java_org_libpag_PAGFile_copyOriginal(JNIEnv* env, jobject thiz) { + auto pagFile = getPAGFile(env, thiz); + if (pagFile == nullptr) { + return NULL; + } + auto newFile = pagFile->copyOriginal(); + return ToPAGLayerJavaObject(env, newFile); + } } \ No newline at end of file diff --git a/src/platform/android/JPAGFont.cpp b/src/platform/android/JPAGFont.cpp index 59f9f3a6cb..611062bc5c 100644 --- a/src/platform/android/JPAGFont.cpp +++ b/src/platform/android/JPAGFont.cpp @@ -23,76 +23,76 @@ using namespace pag; extern "C" { -JNIEXPORT void JNICALL Java_org_libpag_PAGFont_UnregisterFont(JNIEnv* env, jclass, - jstring font_family, - jstring font_style) { - PAGFont::UnregisterFont( - {SafeConvertToStdString(env, font_family), SafeConvertToStdString(env, font_style)}); -} + JNIEXPORT void JNICALL Java_org_libpag_PAGFont_UnregisterFont(JNIEnv* env, jclass, + jstring font_family, + jstring font_style) { + PAGFont::UnregisterFont( + {SafeConvertToStdString(env, font_family), SafeConvertToStdString(env, font_style)}); + } -JNIEXPORT void Java_org_libpag_PAGFont_SetFallbackFontPaths(JNIEnv* env, jclass, - jobjectArray fontNameList, - jintArray ttcIndices) { - std::vector fallbackList; - std::vector ttcList; - auto length = env->GetArrayLength(fontNameList); - auto ttcLength = env->GetArrayLength(ttcIndices); - length = std::min(length, ttcLength); - auto ttcData = env->GetIntArrayElements(ttcIndices, nullptr); - for (int index = 0; index < length; index++) { - jstring fontNameObject = (jstring)env->GetObjectArrayElement(fontNameList, index); - auto fontFamily = SafeConvertToStdString(env, fontNameObject); - env->DeleteLocalRef(fontNameObject); - fallbackList.push_back(fontFamily); - ttcList.push_back(ttcData[index]); - } - env->ReleaseIntArrayElements(ttcIndices, ttcData, 0); - PAGFont::SetFallbackFontPaths(fallbackList, ttcList); -} + JNIEXPORT void Java_org_libpag_PAGFont_SetFallbackFontPaths(JNIEnv* env, jclass, + jobjectArray fontNameList, + jintArray ttcIndices) { + std::vector fallbackList; + std::vector ttcList; + auto length = env->GetArrayLength(fontNameList); + auto ttcLength = env->GetArrayLength(ttcIndices); + length = std::min(length, ttcLength); + auto ttcData = env->GetIntArrayElements(ttcIndices, nullptr); + for (int index = 0; index < length; index++) { + jstring fontNameObject = (jstring)env->GetObjectArrayElement(fontNameList, index); + auto fontFamily = SafeConvertToStdString(env, fontNameObject); + env->DeleteLocalRef(fontNameObject); + fallbackList.push_back(fontFamily); + ttcList.push_back(ttcData[index]); + } + env->ReleaseIntArrayElements(ttcIndices, ttcData, 0); + PAGFont::SetFallbackFontPaths(fallbackList, ttcList); + } -JNIEXPORT jobject JNICALL -Java_org_libpag_PAGFont_RegisterFont__Ljava_lang_String_2ILjava_lang_String_2Ljava_lang_String_2( - JNIEnv* env, jclass, jstring font_path, jint ttc_index, jstring font_family, - jstring font_style) { - auto fontPath = SafeConvertToStdString(env, font_path); - auto font = PAGFont::RegisterFont(fontPath, ttc_index, SafeConvertToStdString(env, font_family), - SafeConvertToStdString(env, font_style)); - if (font.fontFamily.empty()) { - return nullptr; - } - return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); -} + JNIEXPORT jobject JNICALL + Java_org_libpag_PAGFont_RegisterFont__Ljava_lang_String_2ILjava_lang_String_2Ljava_lang_String_2( + JNIEnv* env, jclass, jstring font_path, jint ttc_index, jstring font_family, + jstring font_style) { + auto fontPath = SafeConvertToStdString(env, font_path); + auto font = PAGFont::RegisterFont(fontPath, ttc_index, SafeConvertToStdString(env, font_family), + SafeConvertToStdString(env, font_style)); + if (font.fontFamily.empty()) { + return nullptr; + } + return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); + } -JNIEXPORT jobject JNICALL -Java_org_libpag_PAGFont_RegisterFont__Landroid_content_res_AssetManager_2Ljava_lang_String_2ILjava_lang_String_2Ljava_lang_String_2( - JNIEnv* env, jclass, jobject manager, jstring file_name, jint ttc_index, jstring font_family, - jstring font_style) { - auto path = SafeConvertToStdString(env, file_name); - auto byteData = ReadBytesFromAssets(env, manager, file_name); - if (byteData == nullptr) { - return nullptr; - } - auto font = PAGFont::RegisterFont(byteData->data(), byteData->length(), ttc_index, - SafeConvertToStdString(env, font_family), - SafeConvertToStdString(env, font_style)); - if (font.fontFamily.empty()) { - return nullptr; - } - return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); -} + JNIEXPORT jobject JNICALL + Java_org_libpag_PAGFont_RegisterFont__Landroid_content_res_AssetManager_2Ljava_lang_String_2ILjava_lang_String_2Ljava_lang_String_2( + JNIEnv* env, jclass, jobject manager, jstring file_name, jint ttc_index, jstring font_family, + jstring font_style) { + auto path = SafeConvertToStdString(env, file_name); + auto byteData = ReadBytesFromAssets(env, manager, file_name); + if (byteData == nullptr) { + return nullptr; + } + auto font = PAGFont::RegisterFont(byteData->data(), byteData->length(), ttc_index, + SafeConvertToStdString(env, font_family), + SafeConvertToStdString(env, font_style)); + if (font.fontFamily.empty()) { + return nullptr; + } + return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); + } -JNIEXPORT jobject Java_org_libpag_PAGFont_RegisterFontBytes(JNIEnv* env, jclass, jbyteArray bytes, - jint length, jint ttcIndex, - jstring font_family, - jstring font_style) { - auto data = env->GetByteArrayElements(bytes, nullptr); - auto font = PAGFont::RegisterFont(data, static_cast(length), ttcIndex, - SafeConvertToStdString(env, font_family), - SafeConvertToStdString(env, font_style)); - env->ReleaseByteArrayElements(bytes, data, 0); - if (font.fontFamily.empty()) { - return nullptr; - } - return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); -} + JNIEXPORT jobject Java_org_libpag_PAGFont_RegisterFontBytes(JNIEnv* env, jclass, jbyteArray bytes, + jint length, jint ttcIndex, + jstring font_family, + jstring font_style) { + auto data = env->GetByteArrayElements(bytes, nullptr); + auto font = PAGFont::RegisterFont(data, static_cast(length), ttcIndex, + SafeConvertToStdString(env, font_family), + SafeConvertToStdString(env, font_style)); + env->ReleaseByteArrayElements(bytes, data, 0); + if (font.fontFamily.empty()) { + return nullptr; + } + return MakePAGFontObject(env, font.fontFamily.c_str(), font.fontStyle.c_str()); + } } \ No newline at end of file diff --git a/src/platform/android/JPAGImage.cpp b/src/platform/android/JPAGImage.cpp index 0e9ed9d462..63f67950c9 100644 --- a/src/platform/android/JPAGImage.cpp +++ b/src/platform/android/JPAGImage.cpp @@ -31,185 +31,185 @@ static jfieldID PAGImage_nativeContext; using namespace pag; std::shared_ptr getPAGImage(JNIEnv* env, jobject thiz) { - auto pagImage = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); - if (pagImage == nullptr) { - return nullptr; - } - return pagImage->get(); + auto pagImage = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); + if (pagImage == nullptr) { + return nullptr; + } + return pagImage->get(); } void setPAGImage(JNIEnv* env, jobject thiz, JPAGImage* pagImage) { - auto old = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); - if (old != nullptr) { - delete old; - } - env->SetLongField(thiz, PAGImage_nativeContext, (jlong)pagImage); + auto old = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); + if (old != nullptr) { + delete old; + } + env->SetLongField(thiz, PAGImage_nativeContext, (jlong)pagImage); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGImage_nativeRelease(JNIEnv* env, jobject thiz) { - auto jPagImage = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); - if (jPagImage != nullptr) { - jPagImage->clear(); - } -} - -JNIEXPORT void Java_org_libpag_PAGImage_nativeFinalize(JNIEnv* env, jobject thiz) { - setPAGImage(env, thiz, nullptr); -} - -JNIEXPORT void Java_org_libpag_PAGImage_nativeInit(JNIEnv* env, jclass clazz) { - PAGImage_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); - // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass - // 可能会失败,因此要提前初始化这部分反射方法。 - NativePlatform::InitJNI(env); -} - -JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromBitmap(JNIEnv* env, jclass, jobject bitmap) { - auto info = GetImageInfo(env, bitmap); - if (info.isEmpty()) { - LOGE("PAGImage.LoadFromBitmap() Invalid bitmap specified."); - return 0; - } - void* pixels = nullptr; - if (AndroidBitmap_lockPixels(env, bitmap, &pixels) != 0) { - LOGE("PAGImage.LoadFromBitmap() Invalid bitmap specified."); - return 0; - } - auto pagImage = PAGImage::FromPixels(pixels, info.width(), info.height(), info.rowBytes(), - info.colorType(), info.alphaType()); - AndroidBitmap_unlockPixels(env, bitmap); - if (pagImage == nullptr) { - LOGE("PAGImage.LoadFromPixels() Invalid pixels specified."); - return 0; - } - return reinterpret_cast(new JPAGImage(pagImage)); -} - -JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromPath(JNIEnv* env, jclass, jstring pathObj) { - if (pathObj == nullptr) { - LOGE("PAGImage.LoadFromPath() Invalid path specified."); - return 0; - } - auto path = SafeConvertToStdString(env, pathObj); - if (path.empty()) { - return 0; - } - auto pagImage = PAGImage::FromPath(path); - if (pagImage == nullptr) { - LOGE("PAGImage.LoadFromPath() Invalid image file : %s", path.c_str()); - return 0; - } - return reinterpret_cast(new JPAGImage(pagImage)); -} - -JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromBytes(JNIEnv* env, jclass, jbyteArray bytes, - jint length) { - if (bytes == nullptr) { - LOGE("PAGImage.LoadFromBytes() Invalid image bytes specified."); - return 0; - } - auto data = env->GetByteArrayElements(bytes, nullptr); - auto pagImage = PAGImage::FromBytes(data, static_cast(length)); - env->ReleaseByteArrayElements(bytes, data, 0); - if (pagImage == nullptr) { - LOGE("PAGImage.LoadFromBytes() Invalid image bytes specified."); - return 0; - } - return reinterpret_cast(new JPAGImage(pagImage)); -} - -JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromAssets(JNIEnv* env, jclass, jobject managerObj, - jstring pathObj) { - auto path = SafeConvertToStdString(env, pathObj); - auto byteData = ReadBytesFromAssets(env, managerObj, pathObj); - if (byteData == nullptr) { - LOGE("PAGImage.loadFromAssets() Can't find the file name from asset manager : %s", - path.c_str()); - return 0; - } - auto pagImage = PAGImage::FromBytes(byteData->data(), byteData->length()); - if (pagImage == nullptr) { - LOGE("PAGImage.LoadFromAssets() Invalid image file : %s", path.c_str()); - return 0; - } - return reinterpret_cast(new JPAGImage(pagImage)); -} - -JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromTexture(JNIEnv*, jclass, jint textureID, - jint textureTarget, jint width, - jint height, jboolean flipY) { - GLTextureInfo textureInfo = {}; - textureInfo.target = static_cast(textureTarget); - textureInfo.id = static_cast(textureID); - BackendTexture backendTexture = {textureInfo, width, height}; - auto origin = flipY ? ImageOrigin::BottomLeft : ImageOrigin::TopLeft; - auto image = PAGImage::FromTexture(backendTexture, origin); - if (image == nullptr) { - return 0; - } - auto pagImage = new JPAGImage(image); - return reinterpret_cast(pagImage); -} - -JNIEXPORT jint Java_org_libpag_PAGImage_width(JNIEnv* env, jobject thiz) { - auto image = getPAGImage(env, thiz); - if (image == nullptr) { - return 0; - } - return image->width(); -} - -JNIEXPORT jint Java_org_libpag_PAGImage_height(JNIEnv* env, jobject thiz) { - auto image = getPAGImage(env, thiz); - if (image == nullptr) { - return 0; - } - return image->height(); -} - -JNIEXPORT jint Java_org_libpag_PAGImage_scaleMode(JNIEnv* env, jobject thiz) { - auto image = getPAGImage(env, thiz); - if (image == nullptr) { - return 0; - } - return image->scaleMode(); -} - -JNIEXPORT void Java_org_libpag_PAGImage_setScaleMode(JNIEnv* env, jobject thiz, jint value) { - auto image = getPAGImage(env, thiz); - if (image == nullptr) { - return; - } - image->setScaleMode(value); -} - -JNIEXPORT void Java_org_libpag_PAGImage_nativeGetMatrix(JNIEnv* env, jobject thiz, - jfloatArray values) { - auto list = env->GetFloatArrayElements(values, nullptr); - auto image = getPAGImage(env, thiz); - if (image != nullptr) { - auto matrix = image->matrix(); - matrix.get9(list); - } else { - Matrix matrix = {}; - matrix.setIdentity(); - matrix.get9(list); - } - env->SetFloatArrayRegion(values, 0, 9, list); - env->ReleaseFloatArrayElements(values, list, 0); -} - -JNIEXPORT void Java_org_libpag_PAGImage_nativeSetMatrix(JNIEnv* env, jobject thiz, jfloat a, - jfloat b, jfloat c, jfloat d, jfloat tx, - jfloat ty) { - auto image = getPAGImage(env, thiz); - if (image == nullptr) { - return; - } - Matrix matrix = {}; - matrix.setAll(a, c, tx, b, d, ty, 0, 0, 1); - image->setMatrix(matrix); -} + JNIEXPORT void Java_org_libpag_PAGImage_nativeRelease(JNIEnv* env, jobject thiz) { + auto jPagImage = reinterpret_cast(env->GetLongField(thiz, PAGImage_nativeContext)); + if (jPagImage != nullptr) { + jPagImage->clear(); + } + } + + JNIEXPORT void Java_org_libpag_PAGImage_nativeFinalize(JNIEnv* env, jobject thiz) { + setPAGImage(env, thiz, nullptr); + } + + JNIEXPORT void Java_org_libpag_PAGImage_nativeInit(JNIEnv* env, jclass clazz) { + PAGImage_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass + // 可能会失败,因此要提前初始化这部分反射方法。 + NativePlatform::InitJNI(env); + } + + JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromBitmap(JNIEnv* env, jclass, jobject bitmap) { + auto info = GetImageInfo(env, bitmap); + if (info.isEmpty()) { + LOGE("PAGImage.LoadFromBitmap() Invalid bitmap specified."); + return 0; + } + void* pixels = nullptr; + if (AndroidBitmap_lockPixels(env, bitmap, &pixels) != 0) { + LOGE("PAGImage.LoadFromBitmap() Invalid bitmap specified."); + return 0; + } + auto pagImage = PAGImage::FromPixels(pixels, info.width(), info.height(), info.rowBytes(), + info.colorType(), info.alphaType()); + AndroidBitmap_unlockPixels(env, bitmap); + if (pagImage == nullptr) { + LOGE("PAGImage.LoadFromPixels() Invalid pixels specified."); + return 0; + } + return reinterpret_cast(new JPAGImage(pagImage)); + } + + JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromPath(JNIEnv* env, jclass, jstring pathObj) { + if (pathObj == nullptr) { + LOGE("PAGImage.LoadFromPath() Invalid path specified."); + return 0; + } + auto path = SafeConvertToStdString(env, pathObj); + if (path.empty()) { + return 0; + } + auto pagImage = PAGImage::FromPath(path); + if (pagImage == nullptr) { + LOGE("PAGImage.LoadFromPath() Invalid image file : %s", path.c_str()); + return 0; + } + return reinterpret_cast(new JPAGImage(pagImage)); + } + + JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromBytes(JNIEnv* env, jclass, jbyteArray bytes, + jint length) { + if (bytes == nullptr) { + LOGE("PAGImage.LoadFromBytes() Invalid image bytes specified."); + return 0; + } + auto data = env->GetByteArrayElements(bytes, nullptr); + auto pagImage = PAGImage::FromBytes(data, static_cast(length)); + env->ReleaseByteArrayElements(bytes, data, 0); + if (pagImage == nullptr) { + LOGE("PAGImage.LoadFromBytes() Invalid image bytes specified."); + return 0; + } + return reinterpret_cast(new JPAGImage(pagImage)); + } + + JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromAssets(JNIEnv* env, jclass, jobject managerObj, + jstring pathObj) { + auto path = SafeConvertToStdString(env, pathObj); + auto byteData = ReadBytesFromAssets(env, managerObj, pathObj); + if (byteData == nullptr) { + LOGE("PAGImage.loadFromAssets() Can't find the file name from asset manager : %s", + path.c_str()); + return 0; + } + auto pagImage = PAGImage::FromBytes(byteData->data(), byteData->length()); + if (pagImage == nullptr) { + LOGE("PAGImage.LoadFromAssets() Invalid image file : %s", path.c_str()); + return 0; + } + return reinterpret_cast(new JPAGImage(pagImage)); + } + + JNIEXPORT jlong Java_org_libpag_PAGImage_LoadFromTexture(JNIEnv*, jclass, jint textureID, + jint textureTarget, jint width, + jint height, jboolean flipY) { + GLTextureInfo textureInfo = {}; + textureInfo.target = static_cast(textureTarget); + textureInfo.id = static_cast(textureID); + BackendTexture backendTexture = {textureInfo, width, height}; + auto origin = flipY ? ImageOrigin::BottomLeft : ImageOrigin::TopLeft; + auto image = PAGImage::FromTexture(backendTexture, origin); + if (image == nullptr) { + return 0; + } + auto pagImage = new JPAGImage(image); + return reinterpret_cast(pagImage); + } + + JNIEXPORT jint Java_org_libpag_PAGImage_width(JNIEnv* env, jobject thiz) { + auto image = getPAGImage(env, thiz); + if (image == nullptr) { + return 0; + } + return image->width(); + } + + JNIEXPORT jint Java_org_libpag_PAGImage_height(JNIEnv* env, jobject thiz) { + auto image = getPAGImage(env, thiz); + if (image == nullptr) { + return 0; + } + return image->height(); + } + + JNIEXPORT jint Java_org_libpag_PAGImage_scaleMode(JNIEnv* env, jobject thiz) { + auto image = getPAGImage(env, thiz); + if (image == nullptr) { + return 0; + } + return image->scaleMode(); + } + + JNIEXPORT void Java_org_libpag_PAGImage_setScaleMode(JNIEnv* env, jobject thiz, jint value) { + auto image = getPAGImage(env, thiz); + if (image == nullptr) { + return; + } + image->setScaleMode(value); + } + + JNIEXPORT void Java_org_libpag_PAGImage_nativeGetMatrix(JNIEnv* env, jobject thiz, + jfloatArray values) { + auto list = env->GetFloatArrayElements(values, nullptr); + auto image = getPAGImage(env, thiz); + if (image != nullptr) { + auto matrix = image->matrix(); + matrix.get9(list); + } else { + Matrix matrix = {}; + matrix.setIdentity(); + matrix.get9(list); + } + env->SetFloatArrayRegion(values, 0, 9, list); + env->ReleaseFloatArrayElements(values, list, 0); + } + + JNIEXPORT void Java_org_libpag_PAGImage_nativeSetMatrix(JNIEnv* env, jobject thiz, jfloat a, + jfloat b, jfloat c, jfloat d, jfloat tx, + jfloat ty) { + auto image = getPAGImage(env, thiz); + if (image == nullptr) { + return; + } + Matrix matrix = {}; + matrix.setAll(a, c, tx, b, d, ty, 0, 0, 1); + image->setMatrix(matrix); + } } \ No newline at end of file diff --git a/src/platform/android/JPAGImage.h b/src/platform/android/JPAGImage.h index 96f8c44679..0fede701e7 100644 --- a/src/platform/android/JPAGImage.h +++ b/src/platform/android/JPAGImage.h @@ -21,21 +21,21 @@ #include "pag/pag.h" class JPAGImage { - public: - explicit JPAGImage(std::shared_ptr pagImage) : pagImage(pagImage) { - } +public: + explicit JPAGImage(std::shared_ptr pagImage) : pagImage(pagImage) { + } - std::shared_ptr get() { - std::lock_guard autoLock(locker); - return pagImage; - } + std::shared_ptr get() { + std::lock_guard autoLock(locker); + return pagImage; + } - void clear() { - std::lock_guard autoLock(locker); - pagImage = nullptr; - } + void clear() { + std::lock_guard autoLock(locker); + pagImage = nullptr; + } - private: - std::shared_ptr pagImage; - std::mutex locker; +private: + std::shared_ptr pagImage; + std::mutex locker; }; diff --git a/src/platform/android/JPAGImageLayer.cpp b/src/platform/android/JPAGImageLayer.cpp index 01cc94faed..6bc9d8b77a 100644 --- a/src/platform/android/JPAGImageLayer.cpp +++ b/src/platform/android/JPAGImageLayer.cpp @@ -25,67 +25,67 @@ static jfieldID PAGImageLayer_nativeContext; using namespace pag; std::shared_ptr GetPAGImageLayer(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGImageLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGImageLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGImageLayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGImageLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} + JNIEXPORT void Java_org_libpag_PAGImageLayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGImageLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } -JNIEXPORT jlong Java_org_libpag_PAGImageLayer_nativeMake(JNIEnv*, jclass, jint width, jint height, - jlong duration) { - if (width <= 0 || height <= 0 || duration <= 0) { - return 0; - } - auto pagImageLayer = PAGImageLayer::Make(width, height, duration); - if (pagImageLayer == nullptr) { - return 0; - } - return reinterpret_cast(new JPAGLayerHandle(pagImageLayer)); -} + JNIEXPORT jlong Java_org_libpag_PAGImageLayer_nativeMake(JNIEnv*, jclass, jint width, jint height, + jlong duration) { + if (width <= 0 || height <= 0 || duration <= 0) { + return 0; + } + auto pagImageLayer = PAGImageLayer::Make(width, height, duration); + if (pagImageLayer == nullptr) { + return 0; + } + return reinterpret_cast(new JPAGLayerHandle(pagImageLayer)); + } -JNIEXPORT jobjectArray Java_org_libpag_PAGImageLayer_getVideoRanges(JNIEnv* env, jobject thiz) { - static Global PAGVideoRange_Class(env, env->FindClass("org/libpag/PAGVideoRange")); - auto pagLayer = GetPAGImageLayer(env, thiz); - if (pagLayer == nullptr) { - return env->NewObjectArray(0, PAGVideoRange_Class.get(), nullptr); - } - auto videoRanges = pagLayer->getVideoRanges(); - if (videoRanges.empty()) { - return env->NewObjectArray(0, PAGVideoRange_Class.get(), nullptr); - } - int size = videoRanges.size(); - jobjectArray rangeArray = env->NewObjectArray(size, PAGVideoRange_Class.get(), nullptr); - for (int i = 0; i < size; ++i) { - jobject jRange = ToPAGVideoRangeObject(env, videoRanges[i]); - env->SetObjectArrayElement(rangeArray, i, jRange); - env->DeleteLocalRef(jRange); - } - return rangeArray; -} + JNIEXPORT jobjectArray Java_org_libpag_PAGImageLayer_getVideoRanges(JNIEnv* env, jobject thiz) { + static Global PAGVideoRange_Class(env, env->FindClass("org/libpag/PAGVideoRange")); + auto pagLayer = GetPAGImageLayer(env, thiz); + if (pagLayer == nullptr) { + return env->NewObjectArray(0, PAGVideoRange_Class.get(), nullptr); + } + auto videoRanges = pagLayer->getVideoRanges(); + if (videoRanges.empty()) { + return env->NewObjectArray(0, PAGVideoRange_Class.get(), nullptr); + } + int size = videoRanges.size(); + jobjectArray rangeArray = env->NewObjectArray(size, PAGVideoRange_Class.get(), nullptr); + for (int i = 0; i < size; ++i) { + jobject jRange = ToPAGVideoRangeObject(env, videoRanges[i]); + env->SetObjectArrayElement(rangeArray, i, jRange); + env->DeleteLocalRef(jRange); + } + return rangeArray; + } -JNIEXPORT void Java_org_libpag_PAGImageLayer_replaceImage(JNIEnv* env, jobject thiz, - jlong imageObject) { - auto pagLayer = GetPAGImageLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - auto image = reinterpret_cast(imageObject); - pagLayer->replaceImage(image == nullptr ? nullptr : image->get()); -} + JNIEXPORT void Java_org_libpag_PAGImageLayer_replaceImage(JNIEnv* env, jobject thiz, + jlong imageObject) { + auto pagLayer = GetPAGImageLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + auto image = reinterpret_cast(imageObject); + pagLayer->replaceImage(image == nullptr ? nullptr : image->get()); + } -JNIEXPORT jlong Java_org_libpag_PAGImageLayer_contentDuration(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGImageLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->contentDuration(); -} + JNIEXPORT jlong Java_org_libpag_PAGImageLayer_contentDuration(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGImageLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->contentDuration(); + } } \ No newline at end of file diff --git a/src/platform/android/JPAGLayer.cpp b/src/platform/android/JPAGLayer.cpp index 010b4e72b4..c5e5ecfb71 100644 --- a/src/platform/android/JPAGLayer.cpp +++ b/src/platform/android/JPAGLayer.cpp @@ -24,283 +24,283 @@ static jfieldID PAGLayer_nativeContext; using namespace pag; void SetPAGLayer(JNIEnv* env, jobject thiz, JPAGLayerHandle* nativeContext) { - auto old = reinterpret_cast(env->GetLongField(thiz, PAGLayer_nativeContext)); - if (old != nullptr) { - delete old; - } - env->SetLongField(thiz, PAGLayer_nativeContext, (jlong)nativeContext); + auto old = reinterpret_cast(env->GetLongField(thiz, PAGLayer_nativeContext)); + if (old != nullptr) { + delete old; + } + env->SetLongField(thiz, PAGLayer_nativeContext, (jlong)nativeContext); } std::shared_ptr GetPAGLayer(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return nativeContext->get(); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return nativeContext->get(); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGLayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_nativeRelease(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer != nullptr) { - env->DeleteWeakGlobalRef(static_cast(pagLayer->externalHandle)); - pagLayer->externalHandle = nullptr; - } - SetPAGLayer(env, thiz, nullptr); -} - -JNIEXPORT jint Java_org_libpag_PAGLayer_layerType(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return static_cast(LayerType::Unknown); - } - - return static_cast(pagLayer->layerType()); -} - -JNIEXPORT jstring Java_org_libpag_PAGLayer_layerName(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - std::string name = ""; - if (pagLayer != nullptr) { - name = pagLayer->layerName(); - } - return SafeConvertToJString(env, name.c_str()); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_matrix(JNIEnv* env, jobject thiz, - jfloatArray matrixObject) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - auto matrix = pagLayer->matrix(); - auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); - matrix.get9(matrixArray); - env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setMatrix(JNIEnv* env, jobject thiz, - jfloatArray matrixObject) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - jsize length = env->GetArrayLength(matrixObject); - if (length < 9) { - return; - } - - Matrix matrix = {}; - auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); - matrix.set9(matrixArray); - pagLayer->setMatrix(matrix); - env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_resetMatrix(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - pagLayer->resetMatrix(); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_getTotalMatrix(JNIEnv* env, jobject thiz, - jfloatArray matrixObject) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - Matrix matrix = pagLayer->getTotalMatrix(); - auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); - matrix.get9(matrixArray); - env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); -} - -JNIEXPORT jboolean Java_org_libpag_PAGLayer_visible(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return JNI_FALSE; - } - - return static_cast(pagLayer->visible()); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setVisible(JNIEnv* env, jobject thiz, jboolean visible) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - pagLayer->setVisible(visible); -} - -JNIEXPORT jint Java_org_libpag_PAGLayer_editableIndex(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return -1; - } - - return pagLayer->editableIndex(); -} - -JNIEXPORT jobject Java_org_libpag_PAGLayer_parent(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return nullptr; - } - - std::shared_ptr composition = pagLayer->parent(); - if (composition == nullptr) { - return nullptr; - } - - return ToPAGLayerJavaObject(env, composition); -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGLayer_markers(JNIEnv* env, jobject thiz) { - static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr || pagLayer->markers().empty()) { - return env->NewObjectArray(0, PAGMarker_Class.get(), nullptr); - } - int markerSize = pagLayer->markers().size(); - jobjectArray markerArray = env->NewObjectArray(markerSize, PAGMarker_Class.get(), nullptr); - for (int i = 0; i < markerSize; ++i) { - jobject jMarker = ToPAGMarkerObject(env, pagLayer->markers()[i]); - env->SetObjectArrayElement(markerArray, i, jMarker); - env->DeleteLocalRef(jMarker); - } - return markerArray; -} - -JNIEXPORT jlong Java_org_libpag_PAGLayer_localTimeToGlobal(JNIEnv* env, jobject thiz, jlong time) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return time; - } - return pagLayer->localTimeToGlobal(time); -} - -JNIEXPORT jlong Java_org_libpag_PAGLayer_globalToLocalTime(JNIEnv* env, jobject thiz, jlong time) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return time; - } - return pagLayer->globalToLocalTime(time); -} - -JNIEXPORT jlong Java_org_libpag_PAGLayer_duration(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->duration(); -} - -JNIEXPORT jfloat Java_org_libpag_PAGLayer_frameRate(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return 60; - } - return pagLayer->frameRate(); -} - -JNIEXPORT jlong Java_org_libpag_PAGLayer_startTime(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->startTime(); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setStartTime(JNIEnv* env, jobject thiz, jlong time) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setStartTime(time); -} - -JNIEXPORT jlong Java_org_libpag_PAGLayer_currentTime(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->currentTime(); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setCurrentTime(JNIEnv* env, jobject thiz, jlong time) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setCurrentTime(time); -} - -JNIEXPORT jdouble Java_org_libpag_PAGLayer_getProgress(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->getProgress(); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setProgress(JNIEnv* env, jobject thiz, jdouble progress) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setProgress(progress); -} - -JNIEXPORT jobject Java_org_libpag_PAGLayer_trackMatteLayer(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return nullptr; - } - if (pagLayer->trackMatteLayer() == nullptr) { - return nullptr; - } - return ToPAGLayerJavaObject(env, pagLayer->trackMatteLayer()); -} - -JNIEXPORT jobject Java_org_libpag_PAGLayer_getBounds(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return MakeRectFObject(env, 0.0f, 0.0f, 0.0f, 0.0f); - } - - auto rect = pagLayer->getBounds(); - return MakeRectFObject(env, rect.x(), rect.y(), rect.width(), rect.height()); -} - -JNIEXPORT jboolean Java_org_libpag_PAGLayer_excludedFromTimeline(JNIEnv* env, jobject thiz) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return JNI_FALSE; - } - - return static_cast(pagLayer->excludedFromTimeline()); -} - -JNIEXPORT void Java_org_libpag_PAGLayer_setExcludedFromTimeline(JNIEnv* env, jobject thiz, - jboolean value) { - auto pagLayer = GetPAGLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - - pagLayer->setExcludedFromTimeline(value); -} + JNIEXPORT void Java_org_libpag_PAGLayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_nativeRelease(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer != nullptr) { + env->DeleteWeakGlobalRef(static_cast(pagLayer->externalHandle)); + pagLayer->externalHandle = nullptr; + } + SetPAGLayer(env, thiz, nullptr); + } + + JNIEXPORT jint Java_org_libpag_PAGLayer_layerType(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return static_cast(LayerType::Unknown); + } + + return static_cast(pagLayer->layerType()); + } + + JNIEXPORT jstring Java_org_libpag_PAGLayer_layerName(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + std::string name = ""; + if (pagLayer != nullptr) { + name = pagLayer->layerName(); + } + return SafeConvertToJString(env, name.c_str()); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_matrix(JNIEnv* env, jobject thiz, + jfloatArray matrixObject) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + auto matrix = pagLayer->matrix(); + auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); + matrix.get9(matrixArray); + env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setMatrix(JNIEnv* env, jobject thiz, + jfloatArray matrixObject) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + jsize length = env->GetArrayLength(matrixObject); + if (length < 9) { + return; + } + + Matrix matrix = {}; + auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); + matrix.set9(matrixArray); + pagLayer->setMatrix(matrix); + env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_resetMatrix(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + pagLayer->resetMatrix(); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_getTotalMatrix(JNIEnv* env, jobject thiz, + jfloatArray matrixObject) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + Matrix matrix = pagLayer->getTotalMatrix(); + auto matrixArray = env->GetFloatArrayElements(matrixObject, nullptr); + matrix.get9(matrixArray); + env->ReleaseFloatArrayElements(matrixObject, matrixArray, 0); + } + + JNIEXPORT jboolean Java_org_libpag_PAGLayer_visible(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return JNI_FALSE; + } + + return static_cast(pagLayer->visible()); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setVisible(JNIEnv* env, jobject thiz, jboolean visible) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + pagLayer->setVisible(visible); + } + + JNIEXPORT jint Java_org_libpag_PAGLayer_editableIndex(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return -1; + } + + return pagLayer->editableIndex(); + } + + JNIEXPORT jobject Java_org_libpag_PAGLayer_parent(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return nullptr; + } + + std::shared_ptr composition = pagLayer->parent(); + if (composition == nullptr) { + return nullptr; + } + + return ToPAGLayerJavaObject(env, composition); + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGLayer_markers(JNIEnv* env, jobject thiz) { + static Global PAGMarker_Class(env, env->FindClass("org/libpag/PAGMarker")); + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr || pagLayer->markers().empty()) { + return env->NewObjectArray(0, PAGMarker_Class.get(), nullptr); + } + int markerSize = pagLayer->markers().size(); + jobjectArray markerArray = env->NewObjectArray(markerSize, PAGMarker_Class.get(), nullptr); + for (int i = 0; i < markerSize; ++i) { + jobject jMarker = ToPAGMarkerObject(env, pagLayer->markers()[i]); + env->SetObjectArrayElement(markerArray, i, jMarker); + env->DeleteLocalRef(jMarker); + } + return markerArray; + } + + JNIEXPORT jlong Java_org_libpag_PAGLayer_localTimeToGlobal(JNIEnv* env, jobject thiz, jlong time) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return time; + } + return pagLayer->localTimeToGlobal(time); + } + + JNIEXPORT jlong Java_org_libpag_PAGLayer_globalToLocalTime(JNIEnv* env, jobject thiz, jlong time) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return time; + } + return pagLayer->globalToLocalTime(time); + } + + JNIEXPORT jlong Java_org_libpag_PAGLayer_duration(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->duration(); + } + + JNIEXPORT jfloat Java_org_libpag_PAGLayer_frameRate(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return 60; + } + return pagLayer->frameRate(); + } + + JNIEXPORT jlong Java_org_libpag_PAGLayer_startTime(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->startTime(); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setStartTime(JNIEnv* env, jobject thiz, jlong time) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setStartTime(time); + } + + JNIEXPORT jlong Java_org_libpag_PAGLayer_currentTime(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->currentTime(); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setCurrentTime(JNIEnv* env, jobject thiz, jlong time) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setCurrentTime(time); + } + + JNIEXPORT jdouble Java_org_libpag_PAGLayer_getProgress(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->getProgress(); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setProgress(JNIEnv* env, jobject thiz, jdouble progress) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setProgress(progress); + } + + JNIEXPORT jobject Java_org_libpag_PAGLayer_trackMatteLayer(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return nullptr; + } + if (pagLayer->trackMatteLayer() == nullptr) { + return nullptr; + } + return ToPAGLayerJavaObject(env, pagLayer->trackMatteLayer()); + } + + JNIEXPORT jobject Java_org_libpag_PAGLayer_getBounds(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return MakeRectFObject(env, 0.0f, 0.0f, 0.0f, 0.0f); + } + + auto rect = pagLayer->getBounds(); + return MakeRectFObject(env, rect.x(), rect.y(), rect.width(), rect.height()); + } + + JNIEXPORT jboolean Java_org_libpag_PAGLayer_excludedFromTimeline(JNIEnv* env, jobject thiz) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return JNI_FALSE; + } + + return static_cast(pagLayer->excludedFromTimeline()); + } + + JNIEXPORT void Java_org_libpag_PAGLayer_setExcludedFromTimeline(JNIEnv* env, jobject thiz, + jboolean value) { + auto pagLayer = GetPAGLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + + pagLayer->setExcludedFromTimeline(value); + } } diff --git a/src/platform/android/JPAGLayerHandle.h b/src/platform/android/JPAGLayerHandle.h index caf8d92d59..2fc6eee6a6 100644 --- a/src/platform/android/JPAGLayerHandle.h +++ b/src/platform/android/JPAGLayerHandle.h @@ -21,19 +21,19 @@ #include "pag/pag.h" class JPAGLayerHandle { - public: - explicit JPAGLayerHandle(std::shared_ptr nativeHandle) - : nativeHandle(nativeHandle) { - } +public: + explicit JPAGLayerHandle(std::shared_ptr nativeHandle) + : nativeHandle(nativeHandle) { + } - std::shared_ptr get() { - return nativeHandle; - } + std::shared_ptr get() { + return nativeHandle; + } - void reset() { - nativeHandle = nullptr; - } + void reset() { + nativeHandle = nullptr; + } - private: - std::shared_ptr nativeHandle; +private: + std::shared_ptr nativeHandle; }; diff --git a/src/platform/android/JPAGPlayer.cpp b/src/platform/android/JPAGPlayer.cpp index 04a84ac530..572366721e 100644 --- a/src/platform/android/JPAGPlayer.cpp +++ b/src/platform/android/JPAGPlayer.cpp @@ -29,277 +29,277 @@ static jfieldID PAGPlayer_nativeContext; using namespace pag; std::shared_ptr getPAGPlayer(JNIEnv* env, jobject thiz) { - auto jPlayer = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); - if (jPlayer == nullptr) { - return nullptr; - } - return jPlayer->get(); + auto jPlayer = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); + if (jPlayer == nullptr) { + return nullptr; + } + return jPlayer->get(); } void setPAGPlayer(JNIEnv* env, jobject thiz, JPAGPlayer* player) { - auto old = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); - if (old != nullptr) { - delete old; - } - env->SetLongField(thiz, PAGPlayer_nativeContext, (jlong)player); + auto old = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); + if (old != nullptr) { + delete old; + } + env->SetLongField(thiz, PAGPlayer_nativeContext, (jlong)player); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGPlayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); - // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass - // 可能会失败,因此要提前初始化这部分反射方法。 - NativePlatform::InitJNI(env); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetup(JNIEnv* env, jobject thiz) { - auto player = std::make_shared(); - setPAGPlayer(env, thiz, new JPAGPlayer(player)); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeRelease(JNIEnv* env, jobject thiz) { - auto jPlayer = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); - if (jPlayer != nullptr) { - jPlayer->clear(); - } -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeFinalize(JNIEnv* env, jobject thiz) { - setPAGPlayer(env, thiz, nullptr); -} - -JNIEXPORT jobject Java_org_libpag_PAGPlayer_getComposition(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return nullptr; - } - // 必须从pagPlayer里返回,不能额外存储一个引用,因为同一个PAGComposition添加到别的PAGPlayer后会从当前的移除。 - auto composition = player->getComposition(); - if (composition == nullptr) { - return nullptr; - } - return ToPAGLayerJavaObject(env, composition); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setComposition(JNIEnv* env, jobject thiz, - jobject newComposition) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - auto composition = ToPAGCompositionNativeObject(env, newComposition); - player->setComposition(composition); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetSurface(JNIEnv* env, jobject thiz, - jlong surfaceObject) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - auto surface = reinterpret_cast(surfaceObject); - if (surface != nullptr) { - player->setSurface(surface->get()); - } else { - player->setSurface(nullptr); - } -} - -JNIEXPORT jboolean Java_org_libpag_PAGPlayer_videoEnabled(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return static_cast(player->videoEnabled()); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setVideoEnabled(JNIEnv* env, jobject thiz, - jboolean value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setVideoEnabled(value); -} - -JNIEXPORT jboolean Java_org_libpag_PAGPlayer_cacheEnabled(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return static_cast(player->cacheEnabled()); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setCacheEnabled(JNIEnv* env, jobject thiz, - jboolean value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setCacheEnabled(value); -} - -JNIEXPORT jfloat Java_org_libpag_PAGPlayer_cacheScale(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return player->cacheScale(); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setCacheScale(JNIEnv* env, jobject thiz, jfloat value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setCacheScale(value); -} - -JNIEXPORT jfloat Java_org_libpag_PAGPlayer_maxFrameRate(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return player->maxFrameRate(); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setMaxFrameRate(JNIEnv* env, jobject thiz, jfloat value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setMaxFrameRate(value); -} - -JNIEXPORT jint Java_org_libpag_PAGPlayer_scaleMode(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return player->scaleMode(); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setScaleMode(JNIEnv* env, jobject thiz, jint value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setScaleMode(value); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeGetMatrix(JNIEnv* env, jobject thiz, - jfloatArray values) { - auto list = env->GetFloatArrayElements(values, nullptr); - auto player = getPAGPlayer(env, thiz); - if (player != nullptr) { - auto matrix = player->matrix(); - matrix.get9(list); - } else { - Matrix matrix = {}; - matrix.setIdentity(); - matrix.get9(list); - } - env->SetFloatArrayRegion(values, 0, 9, list); - env->ReleaseFloatArrayElements(values, list, 0); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetMatrix(JNIEnv* env, jobject thiz, jfloat a, - jfloat b, jfloat c, jfloat d, jfloat tx, - jfloat ty) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - Matrix matrix = {}; - matrix.setAll(a, c, tx, b, d, ty, 0, 0, 1); - player->setMatrix(matrix); -} - -JNIEXPORT jlong Java_org_libpag_PAGPlayer_duration(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return player->duration(); -} - -JNIEXPORT jdouble Java_org_libpag_PAGPlayer_getProgress(JNIEnv* env, jobject thiz) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - return player->getProgress(); -} - -JNIEXPORT void Java_org_libpag_PAGPlayer_setProgress(JNIEnv* env, jobject thiz, jdouble value) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return; - } - player->setProgress(value); -} - -JNIEXPORT jboolean Java_org_libpag_PAGPlayer_flushAndFenceSync(JNIEnv* env, jobject thiz, - jlongArray syncArray) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return 0; - } - if (syncArray == nullptr || env->GetArrayLength(syncArray) == 0) { - return static_cast(player->flush()); - } - auto array = env->GetLongArrayElements(syncArray, nullptr); - if (array == nullptr) { - return static_cast(player->flush()); - } - BackendSemaphore semaphore; - auto result = player->flushAndSignalSemaphore(&semaphore); - array[0] = semaphore.isInitialized() ? reinterpret_cast(semaphore.glSync()) : 0; - env->ReleaseLongArrayElements(syncArray, array, 0); - return result; -} - -JNIEXPORT jboolean Java_org_libpag_PAGPlayer_waitSync(JNIEnv* env, jobject thiz, jlong sync) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr || sync == 0) { - return false; - } - BackendSemaphore semaphore; - semaphore.initGL(reinterpret_cast(sync)); - return player->wait(semaphore); -} - -JNIEXPORT jobject Java_org_libpag_PAGPlayer_getBounds(JNIEnv* env, jobject thiz, jobject layer) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return MakeRectFObject(env, 0.0f, 0.0f, 0.0f, 0.0f); - ; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - auto rect = player->getBounds(pagLayer); - return MakeRectFObject(env, rect.x(), rect.y(), rect.width(), rect.height()); -} - -JNIEXPORT jobjectArray Java_org_libpag_PAGPlayer_getLayersUnderPoint(JNIEnv* env, jobject thiz, - jfloat x, jfloat y) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return ToPAGLayerJavaObjectList(env, {}); - } - - auto layers = player->getLayersUnderPoint(x, y); - return ToPAGLayerJavaObjectList(env, layers); -} - -JNIEXPORT jboolean Java_org_libpag_PAGPlayer_hitTestPoint(JNIEnv* env, jobject thiz, jobject layer, - jfloat x, jfloat y, - jboolean pixelHitTest) { - auto player = getPAGPlayer(env, thiz); - if (player == nullptr) { - return JNI_FALSE; - } - auto pagLayer = ToPAGLayerNativeObject(env, layer); - return (jboolean)player->hitTestPoint(pagLayer, x, y, pixelHitTest); -} + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGPlayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass + // 可能会失败,因此要提前初始化这部分反射方法。 + NativePlatform::InitJNI(env); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetup(JNIEnv* env, jobject thiz) { + auto player = std::make_shared(); + setPAGPlayer(env, thiz, new JPAGPlayer(player)); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeRelease(JNIEnv* env, jobject thiz) { + auto jPlayer = reinterpret_cast(env->GetLongField(thiz, PAGPlayer_nativeContext)); + if (jPlayer != nullptr) { + jPlayer->clear(); + } + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeFinalize(JNIEnv* env, jobject thiz) { + setPAGPlayer(env, thiz, nullptr); + } + + JNIEXPORT jobject Java_org_libpag_PAGPlayer_getComposition(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return nullptr; + } + // 必须从pagPlayer里返回,不能额外存储一个引用,因为同一个PAGComposition添加到别的PAGPlayer后会从当前的移除。 + auto composition = player->getComposition(); + if (composition == nullptr) { + return nullptr; + } + return ToPAGLayerJavaObject(env, composition); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setComposition(JNIEnv* env, jobject thiz, + jobject newComposition) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + auto composition = ToPAGCompositionNativeObject(env, newComposition); + player->setComposition(composition); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetSurface(JNIEnv* env, jobject thiz, + jlong surfaceObject) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + auto surface = reinterpret_cast(surfaceObject); + if (surface != nullptr) { + player->setSurface(surface->get()); + } else { + player->setSurface(nullptr); + } + } + + JNIEXPORT jboolean Java_org_libpag_PAGPlayer_videoEnabled(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return static_cast(player->videoEnabled()); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setVideoEnabled(JNIEnv* env, jobject thiz, + jboolean value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setVideoEnabled(value); + } + + JNIEXPORT jboolean Java_org_libpag_PAGPlayer_cacheEnabled(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return static_cast(player->cacheEnabled()); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setCacheEnabled(JNIEnv* env, jobject thiz, + jboolean value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setCacheEnabled(value); + } + + JNIEXPORT jfloat Java_org_libpag_PAGPlayer_cacheScale(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return player->cacheScale(); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setCacheScale(JNIEnv* env, jobject thiz, jfloat value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setCacheScale(value); + } + + JNIEXPORT jfloat Java_org_libpag_PAGPlayer_maxFrameRate(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return player->maxFrameRate(); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setMaxFrameRate(JNIEnv* env, jobject thiz, jfloat value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setMaxFrameRate(value); + } + + JNIEXPORT jint Java_org_libpag_PAGPlayer_scaleMode(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return player->scaleMode(); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setScaleMode(JNIEnv* env, jobject thiz, jint value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setScaleMode(value); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeGetMatrix(JNIEnv* env, jobject thiz, + jfloatArray values) { + auto list = env->GetFloatArrayElements(values, nullptr); + auto player = getPAGPlayer(env, thiz); + if (player != nullptr) { + auto matrix = player->matrix(); + matrix.get9(list); + } else { + Matrix matrix = {}; + matrix.setIdentity(); + matrix.get9(list); + } + env->SetFloatArrayRegion(values, 0, 9, list); + env->ReleaseFloatArrayElements(values, list, 0); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_nativeSetMatrix(JNIEnv* env, jobject thiz, jfloat a, + jfloat b, jfloat c, jfloat d, jfloat tx, + jfloat ty) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + Matrix matrix = {}; + matrix.setAll(a, c, tx, b, d, ty, 0, 0, 1); + player->setMatrix(matrix); + } + + JNIEXPORT jlong Java_org_libpag_PAGPlayer_duration(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return player->duration(); + } + + JNIEXPORT jdouble Java_org_libpag_PAGPlayer_getProgress(JNIEnv* env, jobject thiz) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + return player->getProgress(); + } + + JNIEXPORT void Java_org_libpag_PAGPlayer_setProgress(JNIEnv* env, jobject thiz, jdouble value) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return; + } + player->setProgress(value); + } + + JNIEXPORT jboolean Java_org_libpag_PAGPlayer_flushAndFenceSync(JNIEnv* env, jobject thiz, + jlongArray syncArray) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return 0; + } + if (syncArray == nullptr || env->GetArrayLength(syncArray) == 0) { + return static_cast(player->flush()); + } + auto array = env->GetLongArrayElements(syncArray, nullptr); + if (array == nullptr) { + return static_cast(player->flush()); + } + BackendSemaphore semaphore; + auto result = player->flushAndSignalSemaphore(&semaphore); + array[0] = semaphore.isInitialized() ? reinterpret_cast(semaphore.glSync()) : 0; + env->ReleaseLongArrayElements(syncArray, array, 0); + return result; + } + + JNIEXPORT jboolean Java_org_libpag_PAGPlayer_waitSync(JNIEnv* env, jobject thiz, jlong sync) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr || sync == 0) { + return false; + } + BackendSemaphore semaphore; + semaphore.initGL(reinterpret_cast(sync)); + return player->wait(semaphore); + } + + JNIEXPORT jobject Java_org_libpag_PAGPlayer_getBounds(JNIEnv* env, jobject thiz, jobject layer) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return MakeRectFObject(env, 0.0f, 0.0f, 0.0f, 0.0f); + ; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + auto rect = player->getBounds(pagLayer); + return MakeRectFObject(env, rect.x(), rect.y(), rect.width(), rect.height()); + } + + JNIEXPORT jobjectArray Java_org_libpag_PAGPlayer_getLayersUnderPoint(JNIEnv* env, jobject thiz, + jfloat x, jfloat y) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return ToPAGLayerJavaObjectList(env, {}); + } + + auto layers = player->getLayersUnderPoint(x, y); + return ToPAGLayerJavaObjectList(env, layers); + } + + JNIEXPORT jboolean Java_org_libpag_PAGPlayer_hitTestPoint(JNIEnv* env, jobject thiz, jobject layer, + jfloat x, jfloat y, + jboolean pixelHitTest) { + auto player = getPAGPlayer(env, thiz); + if (player == nullptr) { + return JNI_FALSE; + } + auto pagLayer = ToPAGLayerNativeObject(env, layer); + return (jboolean)player->hitTestPoint(pagLayer, x, y, pixelHitTest); + } } diff --git a/src/platform/android/JPAGPlayer.h b/src/platform/android/JPAGPlayer.h index 2e2270fcc5..abb17fccc8 100644 --- a/src/platform/android/JPAGPlayer.h +++ b/src/platform/android/JPAGPlayer.h @@ -21,21 +21,21 @@ #include "pag/pag.h" class JPAGPlayer { - public: - explicit JPAGPlayer(std::shared_ptr pagPlayer) : pagPlayer(pagPlayer) { - } +public: + explicit JPAGPlayer(std::shared_ptr pagPlayer) : pagPlayer(pagPlayer) { + } - std::shared_ptr get() { - std::lock_guard autoLock(locker); - return pagPlayer; - } + std::shared_ptr get() { + std::lock_guard autoLock(locker); + return pagPlayer; + } - void clear() { - std::lock_guard autoLock(locker); - pagPlayer = nullptr; - } + void clear() { + std::lock_guard autoLock(locker); + pagPlayer = nullptr; + } - private: - std::shared_ptr pagPlayer; - std::mutex locker; +private: + std::shared_ptr pagPlayer; + std::mutex locker; }; diff --git a/src/platform/android/JPAGShapeLayer.cpp b/src/platform/android/JPAGShapeLayer.cpp index fea07c5551..97196a9ad4 100644 --- a/src/platform/android/JPAGShapeLayer.cpp +++ b/src/platform/android/JPAGShapeLayer.cpp @@ -24,17 +24,17 @@ static jfieldID PAGShapeLayer_nativeContext; using namespace pag; std::shared_ptr GetPAGShapeLayer(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGShapeLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGShapeLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGShapeLayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGShapeLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} + JNIEXPORT void Java_org_libpag_PAGShapeLayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGShapeLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } } diff --git a/src/platform/android/JPAGSolidLayer.cpp b/src/platform/android/JPAGSolidLayer.cpp index 677edddcd6..be170f735f 100644 --- a/src/platform/android/JPAGSolidLayer.cpp +++ b/src/platform/android/JPAGSolidLayer.cpp @@ -24,34 +24,34 @@ static jfieldID PAGSolidLayer_nativeContext; using namespace pag; std::shared_ptr GetPAGSolidLayer(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGSolidLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGSolidLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGSolidLayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGSolidLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} - -JNIEXPORT jint Java_org_libpag_PAGSolidLayer_solidColor(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGSolidLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - auto color = pagLayer->solidColor(); - return MakeColorInt(env, color.red, color.green, color.blue); -} - -JNIEXPORT void Java_org_libpag_PAGSolidLayer_setSolidColor(JNIEnv* env, jclass thiz, jint color) { - auto pagLayer = GetPAGSolidLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setSolidColor(ToColor(env, color)); -} + JNIEXPORT void Java_org_libpag_PAGSolidLayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGSolidLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } + + JNIEXPORT jint Java_org_libpag_PAGSolidLayer_solidColor(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGSolidLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + auto color = pagLayer->solidColor(); + return MakeColorInt(env, color.red, color.green, color.blue); + } + + JNIEXPORT void Java_org_libpag_PAGSolidLayer_setSolidColor(JNIEnv* env, jclass thiz, jint color) { + auto pagLayer = GetPAGSolidLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setSolidColor(ToColor(env, color)); + } } diff --git a/src/platform/android/JPAGSurface.cpp b/src/platform/android/JPAGSurface.cpp index e23c9125ca..6fcaef9963 100644 --- a/src/platform/android/JPAGSurface.cpp +++ b/src/platform/android/JPAGSurface.cpp @@ -31,116 +31,116 @@ static jfieldID PAGSurface_nativeSurface; using namespace pag; void setPAGSurface(JNIEnv* env, jobject thiz, JPAGSurface* surface) { - auto old = reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); - if (old != nullptr) { - delete old; - } - env->SetLongField(thiz, PAGSurface_nativeSurface, (jlong)surface); + auto old = reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); + if (old != nullptr) { + delete old; + } + env->SetLongField(thiz, PAGSurface_nativeSurface, (jlong)surface); } std::shared_ptr getPAGSurface(JNIEnv* env, jobject thiz) { - auto pagSurface = - reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); - if (pagSurface == nullptr) { - return nullptr; - } - return pagSurface->get(); + auto pagSurface = + reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); + if (pagSurface == nullptr) { + return nullptr; + } + return pagSurface->get(); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGSurface_nativeInit(JNIEnv* env, jclass clazz) { - PAGSurface_nativeSurface = env->GetFieldID(clazz, "nativeSurface", "J"); - // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass - // 可能会失败,因此要提前初始化这部分反射方法。 - NativePlatform::InitJNI(env); -} - -JNIEXPORT void Java_org_libpag_PAGSurface_nativeRelease(JNIEnv* env, jobject thiz) { - auto jPAGSurface = - reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); - if (jPAGSurface != nullptr) { - jPAGSurface->clear(); - } -} - -JNIEXPORT void Java_org_libpag_PAGSurface_nativeFinalize(JNIEnv* env, jobject thiz) { - setPAGSurface(env, thiz, nullptr); -} - -JNIEXPORT jint Java_org_libpag_PAGSurface_width(JNIEnv* env, jobject thiz) { - auto surface = getPAGSurface(env, thiz); - if (surface == nullptr) { - return 0; - } - return surface->width(); -} - -JNIEXPORT jint Java_org_libpag_PAGSurface_height(JNIEnv* env, jobject thiz) { - auto surface = getPAGSurface(env, thiz); - if (surface == nullptr) { - return 0; - } - return surface->height(); -} - -JNIEXPORT void Java_org_libpag_PAGSurface_updateSize(JNIEnv* env, jobject thiz) { - auto surface = getPAGSurface(env, thiz); - if (surface == nullptr) { - return; - } - surface->updateSize(); -} - -JNIEXPORT jboolean Java_org_libpag_PAGSurface_clearAll(JNIEnv* env, jobject thiz) { - auto surface = getPAGSurface(env, thiz); - if (surface == nullptr) { - return static_cast(false); - } - auto changed = static_cast(surface->clearAll()); - return changed; -} - -JNIEXPORT void Java_org_libpag_PAGSurface_freeCache(JNIEnv* env, jobject thiz) { - auto surface = getPAGSurface(env, thiz); - if (surface == nullptr) { - return; - } - surface->freeCache(); -} - -JNIEXPORT jlong Java_org_libpag_PAGSurface_SetupFromSurfaceWithGLContext(JNIEnv* env, jclass, - jobject surface, - jlong shareContext) { - if (surface == NULL) { - LOGE("PAGSurface.SetupFromSurface() Invalid surface specified."); - return 0; - } - auto nativeWindow = ANativeWindow_fromSurface(env, surface); - auto drawable = GPUDrawable::FromWindow(nativeWindow, reinterpret_cast(shareContext)); - if (drawable == nullptr) { - LOGE("PAGSurface.SetupFromSurface() Invalid surface specified."); - return 0; - } - auto pagSurface = PAGSurface::MakeFrom(drawable); - return reinterpret_cast(new JPAGSurface(pagSurface)); -} - -JNIEXPORT jlong Java_org_libpag_PAGSurface_SetupFromTexture(JNIEnv*, jclass, jint textureID, - jint width, jint height, jboolean flipY, - jboolean forAsyncThread) { - GLTextureInfo glInfo = {}; - glInfo.target = GL::TEXTURE_2D; - glInfo.id = static_cast(textureID); - glInfo.format = GL::RGBA8; - BackendTexture glTexture(glInfo, width, height); - auto origin = flipY ? ImageOrigin::BottomLeft : ImageOrigin::TopLeft; - - auto surface = PAGSurface::MakeFrom(glTexture, origin, forAsyncThread); - if (surface == nullptr) { - LOGE("PAGSurface.SetupFromTexture() Invalid texture specified."); - return 0; - } - return reinterpret_cast(new JPAGSurface(surface)); -} + JNIEXPORT void Java_org_libpag_PAGSurface_nativeInit(JNIEnv* env, jclass clazz) { + PAGSurface_nativeSurface = env->GetFieldID(clazz, "nativeSurface", "J"); + // 调用堆栈源头从C++触发而不是Java触发的情况下,FindClass + // 可能会失败,因此要提前初始化这部分反射方法。 + NativePlatform::InitJNI(env); + } + + JNIEXPORT void Java_org_libpag_PAGSurface_nativeRelease(JNIEnv* env, jobject thiz) { + auto jPAGSurface = + reinterpret_cast(env->GetLongField(thiz, PAGSurface_nativeSurface)); + if (jPAGSurface != nullptr) { + jPAGSurface->clear(); + } + } + + JNIEXPORT void Java_org_libpag_PAGSurface_nativeFinalize(JNIEnv* env, jobject thiz) { + setPAGSurface(env, thiz, nullptr); + } + + JNIEXPORT jint Java_org_libpag_PAGSurface_width(JNIEnv* env, jobject thiz) { + auto surface = getPAGSurface(env, thiz); + if (surface == nullptr) { + return 0; + } + return surface->width(); + } + + JNIEXPORT jint Java_org_libpag_PAGSurface_height(JNIEnv* env, jobject thiz) { + auto surface = getPAGSurface(env, thiz); + if (surface == nullptr) { + return 0; + } + return surface->height(); + } + + JNIEXPORT void Java_org_libpag_PAGSurface_updateSize(JNIEnv* env, jobject thiz) { + auto surface = getPAGSurface(env, thiz); + if (surface == nullptr) { + return; + } + surface->updateSize(); + } + + JNIEXPORT jboolean Java_org_libpag_PAGSurface_clearAll(JNIEnv* env, jobject thiz) { + auto surface = getPAGSurface(env, thiz); + if (surface == nullptr) { + return static_cast(false); + } + auto changed = static_cast(surface->clearAll()); + return changed; + } + + JNIEXPORT void Java_org_libpag_PAGSurface_freeCache(JNIEnv* env, jobject thiz) { + auto surface = getPAGSurface(env, thiz); + if (surface == nullptr) { + return; + } + surface->freeCache(); + } + + JNIEXPORT jlong Java_org_libpag_PAGSurface_SetupFromSurfaceWithGLContext(JNIEnv* env, jclass, + jobject surface, + jlong shareContext) { + if (surface == NULL) { + LOGE("PAGSurface.SetupFromSurface() Invalid surface specified."); + return 0; + } + auto nativeWindow = ANativeWindow_fromSurface(env, surface); + auto drawable = GPUDrawable::FromWindow(nativeWindow, reinterpret_cast(shareContext)); + if (drawable == nullptr) { + LOGE("PAGSurface.SetupFromSurface() Invalid surface specified."); + return 0; + } + auto pagSurface = PAGSurface::MakeFrom(drawable); + return reinterpret_cast(new JPAGSurface(pagSurface)); + } + + JNIEXPORT jlong Java_org_libpag_PAGSurface_SetupFromTexture(JNIEnv*, jclass, jint textureID, + jint width, jint height, jboolean flipY, + jboolean forAsyncThread) { + GLTextureInfo glInfo = {}; + glInfo.target = GL::TEXTURE_2D; + glInfo.id = static_cast(textureID); + glInfo.format = GL::RGBA8; + BackendTexture glTexture(glInfo, width, height); + auto origin = flipY ? ImageOrigin::BottomLeft : ImageOrigin::TopLeft; + + auto surface = PAGSurface::MakeFrom(glTexture, origin, forAsyncThread); + if (surface == nullptr) { + LOGE("PAGSurface.SetupFromTexture() Invalid texture specified."); + return 0; + } + return reinterpret_cast(new JPAGSurface(surface)); + } } diff --git a/src/platform/android/JPAGSurface.h b/src/platform/android/JPAGSurface.h index fd804927a8..c3b333eeb3 100644 --- a/src/platform/android/JPAGSurface.h +++ b/src/platform/android/JPAGSurface.h @@ -21,21 +21,21 @@ #include "pag/pag.h" class JPAGSurface { - public: - explicit JPAGSurface(std::shared_ptr pagSurface) : pagSurface(pagSurface) { - } +public: + explicit JPAGSurface(std::shared_ptr pagSurface) : pagSurface(pagSurface) { + } - std::shared_ptr get() { - std::lock_guard autoLock(locker); - return pagSurface; - } + std::shared_ptr get() { + std::lock_guard autoLock(locker); + return pagSurface; + } - void clear() { - std::lock_guard autoLock(locker); - pagSurface = nullptr; - } + void clear() { + std::lock_guard autoLock(locker); + pagSurface = nullptr; + } - private: - std::shared_ptr pagSurface; - std::mutex locker; +private: + std::shared_ptr pagSurface; + std::mutex locker; }; diff --git a/src/platform/android/JPAGTextLayer.cpp b/src/platform/android/JPAGTextLayer.cpp index cd1c75e629..2308d8af56 100644 --- a/src/platform/android/JPAGTextLayer.cpp +++ b/src/platform/android/JPAGTextLayer.cpp @@ -24,103 +24,103 @@ static jfieldID PAGTextLayer_nativeContext; using namespace pag; std::shared_ptr GetPAGTextLayer(JNIEnv* env, jobject thiz) { - auto nativeContext = - reinterpret_cast(env->GetLongField(thiz, PAGTextLayer_nativeContext)); - if (nativeContext == nullptr) { - return nullptr; - } - return std::static_pointer_cast(nativeContext->get()); + auto nativeContext = + reinterpret_cast(env->GetLongField(thiz, PAGTextLayer_nativeContext)); + if (nativeContext == nullptr) { + return nullptr; + } + return std::static_pointer_cast(nativeContext->get()); } extern "C" { -JNIEXPORT void Java_org_libpag_PAGTextLayer_nativeInit(JNIEnv* env, jclass clazz) { - PAGTextLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); -} - -JNIEXPORT void Java_org_libpag_PAGTextLayer_setFont(JNIEnv* env, jclass thiz, jstring fontFamily, - jstring fontStyle) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setFont( - PAGFont(SafeConvertToStdString(env, fontFamily), SafeConvertToStdString(env, fontStyle))); -} - -JNIEXPORT jobject Java_org_libpag_PAGTextLayer_font(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return nullptr; - } - return MakePAGFontObject(env, pagLayer->font().fontFamily.c_str(), - pagLayer->font().fontStyle.c_str()); -} - -JNIEXPORT jint Java_org_libpag_PAGTextLayer_fillColor(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - auto color = pagLayer->fillColor(); - return MakeColorInt(env, color.red, color.green, color.blue); -} - -JNIEXPORT void Java_org_libpag_PAGTextLayer_setFillColor(JNIEnv* env, jclass thiz, jint color) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setFillColor(ToColor(env, color)); -} - -JNIEXPORT jint Java_org_libpag_PAGTextLayer_strokeColor(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - auto color = pagLayer->strokeColor(); - return MakeColorInt(env, color.red, color.green, color.blue); -} - -JNIEXPORT void Java_org_libpag_PAGTextLayer_setStrokeColor(JNIEnv* env, jclass thiz, jint color) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setStrokeColor(ToColor(env, color)); -} - -JNIEXPORT void Java_org_libpag_PAGTextLayer_setText(JNIEnv* env, jclass thiz, jstring text) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setText(SafeConvertToStdString(env, text)); -} - -JNIEXPORT jstring Java_org_libpag_PAGTextLayer_text(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer != nullptr) { - std::string empty = ""; - return SafeConvertToJString(env, empty.c_str()); - } - return SafeConvertToJString(env, pagLayer->text().c_str()); -} - -JNIEXPORT void Java_org_libpag_PAGTextLayer_setFontSize(JNIEnv* env, jclass thiz, jfloat fontSize) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return; - } - pagLayer->setFontSize(fontSize); -} - -JNIEXPORT jfloat Java_org_libpag_PAGTextLayer_fontSize(JNIEnv* env, jclass thiz) { - auto pagLayer = GetPAGTextLayer(env, thiz); - if (pagLayer == nullptr) { - return 0; - } - return pagLayer->fontSize(); -} + JNIEXPORT void Java_org_libpag_PAGTextLayer_nativeInit(JNIEnv* env, jclass clazz) { + PAGTextLayer_nativeContext = env->GetFieldID(clazz, "nativeContext", "J"); + } + + JNIEXPORT void Java_org_libpag_PAGTextLayer_setFont(JNIEnv* env, jclass thiz, jstring fontFamily, + jstring fontStyle) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setFont( + PAGFont(SafeConvertToStdString(env, fontFamily), SafeConvertToStdString(env, fontStyle))); + } + + JNIEXPORT jobject Java_org_libpag_PAGTextLayer_font(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return nullptr; + } + return MakePAGFontObject(env, pagLayer->font().fontFamily.c_str(), + pagLayer->font().fontStyle.c_str()); + } + + JNIEXPORT jint Java_org_libpag_PAGTextLayer_fillColor(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + auto color = pagLayer->fillColor(); + return MakeColorInt(env, color.red, color.green, color.blue); + } + + JNIEXPORT void Java_org_libpag_PAGTextLayer_setFillColor(JNIEnv* env, jclass thiz, jint color) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setFillColor(ToColor(env, color)); + } + + JNIEXPORT jint Java_org_libpag_PAGTextLayer_strokeColor(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + auto color = pagLayer->strokeColor(); + return MakeColorInt(env, color.red, color.green, color.blue); + } + + JNIEXPORT void Java_org_libpag_PAGTextLayer_setStrokeColor(JNIEnv* env, jclass thiz, jint color) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setStrokeColor(ToColor(env, color)); + } + + JNIEXPORT void Java_org_libpag_PAGTextLayer_setText(JNIEnv* env, jclass thiz, jstring text) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setText(SafeConvertToStdString(env, text)); + } + + JNIEXPORT jstring Java_org_libpag_PAGTextLayer_text(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer != nullptr) { + std::string empty = ""; + return SafeConvertToJString(env, empty.c_str()); + } + return SafeConvertToJString(env, pagLayer->text().c_str()); + } + + JNIEXPORT void Java_org_libpag_PAGTextLayer_setFontSize(JNIEnv* env, jclass thiz, jfloat fontSize) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return; + } + pagLayer->setFontSize(fontSize); + } + + JNIEXPORT jfloat Java_org_libpag_PAGTextLayer_fontSize(JNIEnv* env, jclass thiz) { + auto pagLayer = GetPAGTextLayer(env, thiz); + if (pagLayer == nullptr) { + return 0; + } + return pagLayer->fontSize(); + } } diff --git a/src/platform/android/JStringUtil.cpp b/src/platform/android/JStringUtil.cpp index 892ba830c7..f4cdf55831 100644 --- a/src/platform/android/JStringUtil.cpp +++ b/src/platform/android/JStringUtil.cpp @@ -24,39 +24,39 @@ * So we use this method instead. */ jstring SafeConvertToJString(JNIEnv* env, const char* text) { - static Global StringClass(env, env->FindClass("java/lang/String")); - static jmethodID StringConstructID = - env->GetMethodID(StringClass.get(), "", "([BLjava/lang/String;)V"); - int length = strlen(text); - jbyteArray array = env->NewByteArray(length); - env->SetByteArrayRegion(array, 0, length, reinterpret_cast(text)); - jstring stringUTF = env->NewStringUTF("UTF-8"); - jstring object = (jstring)env->NewObject(StringClass.get(), StringConstructID, array, stringUTF); - env->DeleteLocalRef(stringUTF); - env->DeleteLocalRef(array); - return object; + static Global StringClass(env, env->FindClass("java/lang/String")); + static jmethodID StringConstructID = + env->GetMethodID(StringClass.get(), "", "([BLjava/lang/String;)V"); + int length = strlen(text); + jbyteArray array = env->NewByteArray(length); + env->SetByteArrayRegion(array, 0, length, reinterpret_cast(text)); + jstring stringUTF = env->NewStringUTF("UTF-8"); + jstring object = (jstring)env->NewObject(StringClass.get(), StringConstructID, array, stringUTF); + env->DeleteLocalRef(stringUTF); + env->DeleteLocalRef(array); + return object; } std::string SafeConvertToStdString(JNIEnv* env, jstring jText) { - if (jText == NULL) { - return ""; - } - std::string result; - static Global StringClass(env, env->FindClass("java/lang/String")); - static jmethodID GetBytesID = - env->GetMethodID(StringClass.get(), "getBytes", "(Ljava/lang/String;)[B"); - jstring encoding = env->NewStringUTF("utf-8"); + if (jText == NULL) { + return ""; + } + std::string result; + static Global StringClass(env, env->FindClass("java/lang/String")); + static jmethodID GetBytesID = + env->GetMethodID(StringClass.get(), "getBytes", "(Ljava/lang/String;)[B"); + jstring encoding = env->NewStringUTF("utf-8"); - jbyteArray jBytes = (jbyteArray)env->CallObjectMethod(jText, GetBytesID, encoding); - env->DeleteLocalRef(encoding); + jbyteArray jBytes = (jbyteArray)env->CallObjectMethod(jText, GetBytesID, encoding); + env->DeleteLocalRef(encoding); - jsize textLength = env->GetArrayLength(jBytes); - if (textLength > 0) { - char* bytes = new char[textLength]; - env->GetByteArrayRegion(jBytes, 0, textLength, (jbyte*)bytes); - result = std::string(bytes, (unsigned)textLength); - delete[] bytes; - } - env->DeleteLocalRef(jBytes); - return result; + jsize textLength = env->GetArrayLength(jBytes); + if (textLength > 0) { + char* bytes = new char[textLength]; + env->GetByteArrayRegion(jBytes, 0, textLength, (jbyte*)bytes); + result = std::string(bytes, (unsigned)textLength); + delete[] bytes; + } + env->DeleteLocalRef(jBytes); + return result; } \ No newline at end of file diff --git a/src/platform/android/JTraceImage.cpp b/src/platform/android/JTraceImage.cpp index 34227555d6..8fbd164c9b 100644 --- a/src/platform/android/JTraceImage.cpp +++ b/src/platform/android/JTraceImage.cpp @@ -24,32 +24,32 @@ static Global TraceImageClass; static jmethodID TraceImage_Trace; void JTraceImage::InitJNI(JNIEnv* env) { - TraceImageClass.reset(env, env->FindClass("org/libpag/TraceImage")); - TraceImage_Trace = env->GetStaticMethodID(TraceImageClass.get(), "Trace", - "(Ljava/lang/String;Ljava/nio/ByteBuffer;II)V"); + TraceImageClass.reset(env, env->FindClass("org/libpag/TraceImage")); + TraceImage_Trace = env->GetStaticMethodID(TraceImageClass.get(), "Trace", + "(Ljava/lang/String;Ljava/nio/ByteBuffer;II)V"); } void JTraceImage::Trace(const PixelMap& pixelMap, const std::string& tag) { - auto env = JNIEnvironment::Current(); - if (env == nullptr || pixelMap.isEmpty()) { - return; - } + auto env = JNIEnvironment::Current(); + if (env == nullptr || pixelMap.isEmpty()) { + return; + } - auto rowBytes = static_cast(pixelMap.width() * 4); - auto pixels = new (std::nothrow) uint8_t[pixelMap.height() * rowBytes]; - if (pixels == nullptr) { - return; - } - auto info = ImageInfo::Make(pixelMap.width(), pixelMap.height(), ColorType::RGBA_8888, - AlphaType::Premultiplied, rowBytes); - pixelMap.readPixels(info, pixels); - auto byteBuffer = - MakeByteBufferObject(env, pixels, static_cast(pixelMap.height() * rowBytes)); - auto tagString = SafeConvertToJString(env, tag.c_str()); - env->CallStaticVoidMethod(TraceImageClass.get(), TraceImage_Trace, tagString, byteBuffer, - pixelMap.width(), pixelMap.height()); - env->DeleteLocalRef(byteBuffer); - env->DeleteLocalRef(tagString); - delete[] pixels; + auto rowBytes = static_cast(pixelMap.width() * 4); + auto pixels = new (std::nothrow) uint8_t[pixelMap.height() * rowBytes]; + if (pixels == nullptr) { + return; + } + auto info = ImageInfo::Make(pixelMap.width(), pixelMap.height(), ColorType::RGBA_8888, + AlphaType::Premultiplied, rowBytes); + pixelMap.readPixels(info, pixels); + auto byteBuffer = + MakeByteBufferObject(env, pixels, static_cast(pixelMap.height() * rowBytes)); + auto tagString = SafeConvertToJString(env, tag.c_str()); + env->CallStaticVoidMethod(TraceImageClass.get(), TraceImage_Trace, tagString, byteBuffer, + pixelMap.width(), pixelMap.height()); + env->DeleteLocalRef(byteBuffer); + env->DeleteLocalRef(tagString); + delete[] pixels; } } // namespace pag diff --git a/src/platform/android/JTraceImage.h b/src/platform/android/JTraceImage.h index 20971a0747..d970150e17 100644 --- a/src/platform/android/JTraceImage.h +++ b/src/platform/android/JTraceImage.h @@ -23,9 +23,9 @@ namespace pag { class JTraceImage { - public: - static void InitJNI(JNIEnv* env); +public: + static void InitJNI(JNIEnv* env); - static void Trace(const PixelMap& pixelMap, const std::string& tag); + static void Trace(const PixelMap& pixelMap, const std::string& tag); }; } // namespace pag diff --git a/src/platform/android/JVideoDecoder.cpp b/src/platform/android/JVideoDecoder.cpp index e343acb86e..c5cd8ddb03 100644 --- a/src/platform/android/JVideoDecoder.cpp +++ b/src/platform/android/JVideoDecoder.cpp @@ -20,14 +20,14 @@ #include "platform/android/GPUDecoder.h" extern "C" { -JNIEXPORT void Java_org_libpag_VideoDecoder_RegisterSoftwareDecoderFactory(JNIEnv*, jclass, - jlong factory) { - pag::PAGVideoDecoder::RegisterSoftwareDecoderFactory( - reinterpret_cast(factory)); -} + JNIEXPORT void Java_org_libpag_VideoDecoder_RegisterSoftwareDecoderFactory(JNIEnv*, jclass, + jlong factory) { + pag::PAGVideoDecoder::RegisterSoftwareDecoderFactory( + reinterpret_cast(factory)); + } -JNIEXPORT void Java_org_libpag_VideoDecoder_SetMaxHardwareDecoderCount(JNIEnv*, jclass, - jint maxCount) { - pag::PAGVideoDecoder::SetMaxHardwareDecoderCount(maxCount); -} + JNIEXPORT void Java_org_libpag_VideoDecoder_SetMaxHardwareDecoderCount(JNIEnv*, jclass, + jint maxCount) { + pag::PAGVideoDecoder::SetMaxHardwareDecoderCount(maxCount); + } } diff --git a/src/platform/android/NativeGLDevice.cpp b/src/platform/android/NativeGLDevice.cpp index e63051b8aa..af092cecff 100644 --- a/src/platform/android/NativeGLDevice.cpp +++ b/src/platform/android/NativeGLDevice.cpp @@ -21,15 +21,15 @@ namespace pag { void* NativeGLDevice::GetCurrentNativeHandle() { - return eglGetCurrentContext(); + return eglGetCurrentContext(); } std::shared_ptr NativeGLDevice::Current() { - return EGLDevice::Current(); + return EGLDevice::Current(); } std::shared_ptr NativeGLDevice::Make(void* sharedContext) { - return EGLDevice::Make(sharedContext); + return EGLDevice::Make(sharedContext); } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/NativeGraphicBuffer.cpp b/src/platform/android/NativeGraphicBuffer.cpp index ffae4cb3ab..4d0b2ce457 100644 --- a/src/platform/android/NativeGraphicBuffer.cpp +++ b/src/platform/android/NativeGraphicBuffer.cpp @@ -23,72 +23,72 @@ namespace pag { std::shared_ptr NativeGraphicBuffer::MakeAdopted( android::GraphicBuffer* graphicBuffer) { - if (!graphicBuffer || !NativeGraphicBufferInterface::Get()->constructor) { - return nullptr; - } - return std::shared_ptr(new NativeGraphicBuffer(graphicBuffer)); + if (!graphicBuffer || !NativeGraphicBufferInterface::Get()->constructor) { + return nullptr; + } + return std::shared_ptr(new NativeGraphicBuffer(graphicBuffer)); } std::shared_ptr NativeGraphicBuffer::Make(int width, int height, bool alphaOnly) { - if (alphaOnly) { - return nullptr; - } - if (!NativeGraphicBufferInterface::Get()->constructor) { - return nullptr; - } - auto buffer = NativeGraphicBufferInterface::MakeGraphicBuffer( - width, height, PIXEL_FORMAT_RGBA_8888, - NativeGraphicBufferInterface::USAGE_HW_RENDER | - NativeGraphicBufferInterface::USAGE_HW_TEXTURE | - NativeGraphicBufferInterface::USAGE_HW_RENDER | - NativeGraphicBufferInterface::USAGE_SW_READ_OFTEN | - NativeGraphicBufferInterface::USAGE_SW_WRITE_OFTEN); - if (!buffer) { - return nullptr; - } - return std::shared_ptr(new NativeGraphicBuffer(buffer)); + if (alphaOnly) { + return nullptr; + } + if (!NativeGraphicBufferInterface::Get()->constructor) { + return nullptr; + } + auto buffer = NativeGraphicBufferInterface::MakeGraphicBuffer( + width, height, PIXEL_FORMAT_RGBA_8888, + NativeGraphicBufferInterface::USAGE_HW_RENDER | + NativeGraphicBufferInterface::USAGE_HW_TEXTURE | + NativeGraphicBufferInterface::USAGE_HW_RENDER | + NativeGraphicBufferInterface::USAGE_SW_READ_OFTEN | + NativeGraphicBufferInterface::USAGE_SW_WRITE_OFTEN); + if (!buffer) { + return nullptr; + } + return std::shared_ptr(new NativeGraphicBuffer(buffer)); } std::shared_ptr NativeGraphicBuffer::makeTexture(Context* context) const { - return GLHardwareTexture::MakeFrom(context, graphicBuffer); + return GLHardwareTexture::MakeFrom(context, graphicBuffer); } void* NativeGraphicBuffer::lockPixels() { - uint8_t* readPtr = nullptr; - if (graphicBuffer) { - NativeGraphicBufferInterface::Get()->lock( - graphicBuffer, - NativeGraphicBufferInterface::USAGE_SW_READ_OFTEN | + uint8_t* readPtr = nullptr; + if (graphicBuffer) { + NativeGraphicBufferInterface::Get()->lock( + graphicBuffer, + NativeGraphicBufferInterface::USAGE_SW_READ_OFTEN | NativeGraphicBufferInterface::USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&readPtr)); - } - return readPtr; + reinterpret_cast(&readPtr)); + } + return readPtr; } void NativeGraphicBuffer::unlockPixels() { - if (graphicBuffer) { - NativeGraphicBufferInterface::Get()->unlock(graphicBuffer); - } + if (graphicBuffer) { + NativeGraphicBufferInterface::Get()->unlock(graphicBuffer); + } } static ImageInfo GetImageInfo(android::GraphicBuffer* graphicBuffer) { - auto desc = - (android::android_native_buffer_t*)NativeGraphicBufferInterface::Get()->getNativeBuffer( - graphicBuffer); - return ImageInfo::Make(desc->width, desc->height, ColorType::RGBA_8888, AlphaType::Premultiplied, - desc->stride * 4); + auto desc = + (android::android_native_buffer_t*)NativeGraphicBufferInterface::Get()->getNativeBuffer( + graphicBuffer); + return ImageInfo::Make(desc->width, desc->height, ColorType::RGBA_8888, AlphaType::Premultiplied, + desc->stride * 4); } NativeGraphicBuffer::NativeGraphicBuffer(android::GraphicBuffer* graphicBuffer) : PixelBuffer(GetImageInfo(graphicBuffer)), graphicBuffer(graphicBuffer) { - if (graphicBuffer) { - NativeGraphicBufferInterface::Acquire(graphicBuffer); - } + if (graphicBuffer) { + NativeGraphicBufferInterface::Acquire(graphicBuffer); + } } NativeGraphicBuffer::~NativeGraphicBuffer() { - if (graphicBuffer) { - NativeGraphicBufferInterface::Release(graphicBuffer); - } + if (graphicBuffer) { + NativeGraphicBufferInterface::Release(graphicBuffer); + } } } // namespace pag diff --git a/src/platform/android/NativeGraphicBuffer.h b/src/platform/android/NativeGraphicBuffer.h index 9cde62ab8f..5dddd846ac 100644 --- a/src/platform/android/NativeGraphicBuffer.h +++ b/src/platform/android/NativeGraphicBuffer.h @@ -23,22 +23,22 @@ namespace pag { class NativeGraphicBuffer : public PixelBuffer { - public: - static std::shared_ptr Make(int width, int height, bool alphaOnly); +public: + static std::shared_ptr Make(int width, int height, bool alphaOnly); - static std::shared_ptr MakeAdopted(android::GraphicBuffer* graphicBuffer); + static std::shared_ptr MakeAdopted(android::GraphicBuffer* graphicBuffer); - ~NativeGraphicBuffer() override; + ~NativeGraphicBuffer() override; - void* lockPixels() override; + void* lockPixels() override; - void unlockPixels() override; + void unlockPixels() override; - std::shared_ptr makeTexture(Context*) const override; + std::shared_ptr makeTexture(Context*) const override; - NativeGraphicBuffer(android::GraphicBuffer* graphicBuffer); + NativeGraphicBuffer(android::GraphicBuffer* graphicBuffer); - private: - android::GraphicBuffer* graphicBuffer = nullptr; +private: + android::GraphicBuffer* graphicBuffer = nullptr; }; } // namespace pag \ No newline at end of file diff --git a/src/platform/android/NativeGraphicBufferInterface.cpp b/src/platform/android/NativeGraphicBufferInterface.cpp index a2d14e8e8a..da0d3afb0e 100644 --- a/src/platform/android/NativeGraphicBufferInterface.cpp +++ b/src/platform/android/NativeGraphicBufferInterface.cpp @@ -39,114 +39,114 @@ const int GRAPHICBUFFER_SIZE = 1024; template RT* callConstructor4(void (*fptr)(), void* memory, T1 param1, T2 param2, T3 param3, T4 param4) { #if defined(CPU_ARM) - // C1 constructors return pointer - typedef RT* (*ABIFptr)(void*, T1, T2, T3, T4); - (void)((ABIFptr)fptr)(memory, param1, param2, param3, param4); - return reinterpret_cast(memory); + // C1 constructors return pointer + typedef RT* (*ABIFptr)(void*, T1, T2, T3, T4); + (void)((ABIFptr)fptr)(memory, param1, param2, param3, param4); + return reinterpret_cast(memory); #elif defined(CPU_ARM_64) - // C1 constructors return void - typedef void (*ABIFptr)(void*, T1, T2, T3, T4); - ((ABIFptr)fptr)(memory, param1, param2, param3, param4); - return reinterpret_cast(memory); + // C1 constructors return void + typedef void (*ABIFptr)(void*, T1, T2, T3, T4); + ((ABIFptr)fptr)(memory, param1, param2, param3, param4); + return reinterpret_cast(memory); #elif defined(CPU_X86) || defined(CPU_X86_64) - // ctor returns void - typedef void (*ABIFptr)(void*, T1, T2, T3, T4); - ((ABIFptr)fptr)(memory, param1, param2, param3, param4); - return reinterpret_cast(memory); + // ctor returns void + typedef void (*ABIFptr)(void*, T1, T2, T3, T4); + ((ABIFptr)fptr)(memory, param1, param2, param3, param4); + return reinterpret_cast(memory); #else - return nullptr; + return nullptr; #endif } template void callDestructor(void (*fptr)(), T* obj) { #if defined(CPU_ARM) - // D1 destructor returns ptr - typedef void* (*ABIFptr)(T * obj); - (void)((ABIFptr)fptr)(obj); + // D1 destructor returns ptr + typedef void* (*ABIFptr)(T * obj); + (void)((ABIFptr)fptr)(obj); #elif defined(CPU_ARM_64) - // D1 destructor returns void - typedef void (*ABIFptr)(T * obj); - ((ABIFptr)fptr)(obj); + // D1 destructor returns void + typedef void (*ABIFptr)(T * obj); + ((ABIFptr)fptr)(obj); #elif defined(CPU_X86) || defined(CPU_X86_64) - // dtor returns void - typedef void (*ABIFptr)(T * obj); - ((ABIFptr)fptr)(obj); + // dtor returns void + typedef void (*ABIFptr)(T * obj); + ((ABIFptr)fptr)(obj); #endif } template static void loadSymbol(void* libHandle, T*& pfn, const char* symbol) { - pfn = (T*)dlsym(libHandle, symbol); + pfn = (T*)dlsym(libHandle, symbol); } NativeGraphicBufferInterface* NativeGraphicBufferInterface::Get() { - static NativeGraphicBufferInterface instance; - return &instance; + static NativeGraphicBufferInterface instance; + return &instance; } NativeGraphicBufferInterface::NativeGraphicBufferInterface() { - libHandle = dlopen("libui.so", RTLD_LAZY); - if (!libHandle) return; - loadSymbol(libHandle, constructor, "_ZN7android13GraphicBufferC1Ejjij"); - loadSymbol(libHandle, destructor, "_ZN7android13GraphicBufferD1Ev"); - loadSymbol(libHandle, getNativeBuffer, "_ZNK7android13GraphicBuffer15getNativeBufferEv"); - loadSymbol(libHandle, lock, "_ZN7android13GraphicBuffer4lockEjPPv"); - loadSymbol(libHandle, unlock, "_ZN7android13GraphicBuffer6unlockEv"); - loadSymbol(libHandle, initCheck, "_ZNK7android13GraphicBuffer9initCheckEv"); - if (constructor && destructor && getNativeBuffer && lock && unlock && initCheck) { - return; - } - constructor = nullptr; + libHandle = dlopen("libui.so", RTLD_LAZY); + if (!libHandle) return; + loadSymbol(libHandle, constructor, "_ZN7android13GraphicBufferC1Ejjij"); + loadSymbol(libHandle, destructor, "_ZN7android13GraphicBufferD1Ev"); + loadSymbol(libHandle, getNativeBuffer, "_ZNK7android13GraphicBuffer15getNativeBufferEv"); + loadSymbol(libHandle, lock, "_ZN7android13GraphicBuffer4lockEjPPv"); + loadSymbol(libHandle, unlock, "_ZN7android13GraphicBuffer6unlockEv"); + loadSymbol(libHandle, initCheck, "_ZNK7android13GraphicBuffer9initCheckEv"); + if (constructor && destructor && getNativeBuffer && lock && unlock && initCheck) { + return; + } + constructor = nullptr; } NativeGraphicBufferInterface::~NativeGraphicBufferInterface() { - if (libHandle) { - dlclose(libHandle); - } + if (libHandle) { + dlclose(libHandle); + } } template T1* pointerToOffset(T2* ptr, size_t bytes) { - return reinterpret_cast((uint8_t*)ptr + bytes); + return reinterpret_cast((uint8_t*)ptr + bytes); } android::GraphicBuffer* NativeGraphicBufferInterface::MakeGraphicBuffer(uint32_t width, - uint32_t height, - PixelFormat format, - uint32_t usage) { - auto interface = NativeGraphicBufferInterface::Get(); - void* const memory = malloc(GRAPHICBUFFER_SIZE); - if (memory == nullptr) { - return nullptr; - } - android::GraphicBuffer* graphicBuffer = - callConstructor4( - interface->constructor, memory, width, height, format, usage); - android::android_native_base_t* const base = GetAndroidNativeBase(graphicBuffer); - status_t ctorStatus = interface->initCheck(graphicBuffer); - const uint32_t expectedVersion = sizeof(void*) == 4 ? 96 : 168; - if (ctorStatus || base->magic != 0x5f626672u || base->version != expectedVersion) { - callDestructor(interface->destructor, graphicBuffer); - return nullptr; - } - return graphicBuffer; + uint32_t height, + PixelFormat format, + uint32_t usage) { + auto interface = NativeGraphicBufferInterface::Get(); + void* const memory = malloc(GRAPHICBUFFER_SIZE); + if (memory == nullptr) { + return nullptr; + } + android::GraphicBuffer* graphicBuffer = + callConstructor4( + interface->constructor, memory, width, height, format, usage); + android::android_native_base_t* const base = GetAndroidNativeBase(graphicBuffer); + status_t ctorStatus = interface->initCheck(graphicBuffer); + const uint32_t expectedVersion = sizeof(void*) == 4 ? 96 : 168; + if (ctorStatus || base->magic != 0x5f626672u || base->version != expectedVersion) { + callDestructor(interface->destructor, graphicBuffer); + return nullptr; + } + return graphicBuffer; } android::android_native_base_t* NativeGraphicBufferInterface::GetAndroidNativeBase( const android::GraphicBuffer* buffer) { - return pointerToOffset(buffer, 2 * sizeof(void*)); + return pointerToOffset(buffer, 2 * sizeof(void*)); } void NativeGraphicBufferInterface::Acquire(android::GraphicBuffer* buffer) { - auto nativeBuffer = GetAndroidNativeBase(buffer); - nativeBuffer->incRef(nativeBuffer); + auto nativeBuffer = GetAndroidNativeBase(buffer); + nativeBuffer->incRef(nativeBuffer); } void NativeGraphicBufferInterface::Release(android::GraphicBuffer* buffer) { - auto nativeBuffer = GetAndroidNativeBase(buffer); - if (nativeBuffer) { - nativeBuffer->decRef(nativeBuffer); - } + auto nativeBuffer = GetAndroidNativeBase(buffer); + if (nativeBuffer) { + nativeBuffer->decRef(nativeBuffer); + } } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/NativeGraphicBufferInterface.h b/src/platform/android/NativeGraphicBufferInterface.h index ed6375b4ca..ec54bb717a 100644 --- a/src/platform/android/NativeGraphicBufferInterface.h +++ b/src/platform/android/NativeGraphicBufferInterface.h @@ -11,106 +11,106 @@ class GraphicBuffer; // include/system/window.h struct android_native_base_t { - uint32_t magic; - uint32_t version; - void* reserved[4]; - void (*incRef)(struct android_native_base_t* base); - void (*decRef)(struct android_native_base_t* base); + uint32_t magic; + uint32_t version; + void* reserved[4]; + void (*incRef)(struct android_native_base_t* base); + void (*decRef)(struct android_native_base_t* base); }; // include/ui/android_native_buffer.h struct android_native_buffer_t { - struct android_native_base_t common; - int32_t width; - int32_t height; - int32_t stride; - int32_t format; - int32_t usage; - // ... + struct android_native_base_t common; + int32_t width; + int32_t height; + int32_t stride; + int32_t format; + int32_t usage; + // ... }; } // namespace android // ui/PixelFormat.h, system/graphics.h enum PixelFormat { - PIXEL_FORMAT_UNKNOWN = 0, - PIXEL_FORMAT_NONE = 0, - PIXEL_FORMAT_CUSTOM = -4, - PIXEL_FORMAT_TRANSLUCENT = -3, - PIXEL_FORMAT_TRANSPARENT = -2, - PIXEL_FORMAT_OPAQUE = -1, - PIXEL_FORMAT_RGBA_8888 = 1, - PIXEL_FORMAT_RGBX_8888 = 2, - PIXEL_FORMAT_RGB_888 = 3, - PIXEL_FORMAT_RGB_565 = 4, - PIXEL_FORMAT_BGRA_8888 = 5, - PIXEL_FORMAT_RGBA_5551 = 6, - PIXEL_FORMAT_RGBA_4444 = 7, + PIXEL_FORMAT_UNKNOWN = 0, + PIXEL_FORMAT_NONE = 0, + PIXEL_FORMAT_CUSTOM = -4, + PIXEL_FORMAT_TRANSLUCENT = -3, + PIXEL_FORMAT_TRANSPARENT = -2, + PIXEL_FORMAT_OPAQUE = -1, + PIXEL_FORMAT_RGBA_8888 = 1, + PIXEL_FORMAT_RGBX_8888 = 2, + PIXEL_FORMAT_RGB_888 = 3, + PIXEL_FORMAT_RGB_565 = 4, + PIXEL_FORMAT_BGRA_8888 = 5, + PIXEL_FORMAT_RGBA_5551 = 6, + PIXEL_FORMAT_RGBA_4444 = 7, }; namespace pag { // utils/Errors.h enum status_t { - OK = 0, - UNKNOWN_ERROR = (-2147483647 - 1), - NO_MEMORY = -ENOMEM, - INVALID_OPERATION = -ENOSYS, - BAD_VALUE = -EINVAL, - BAD_TYPE = (UNKNOWN_ERROR + 1), - NAME_NOT_FOUND = -ENOENT, - PERMISSION_DENIED = -EPERM, - NO_INIT = -ENODEV, - ALREADY_EXISTS = -EEXIST, - DEAD_OBJECT = -EPIPE, - FAILED_TRANSACTION = (UNKNOWN_ERROR + 2), - BAD_INDEX = -E2BIG, - NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3), - WOULD_BLOCK = (UNKNOWN_ERROR + 4), - TIMED_OUT = (UNKNOWN_ERROR + 5), - UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6), - FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7), + OK = 0, + UNKNOWN_ERROR = (-2147483647 - 1), + NO_MEMORY = -ENOMEM, + INVALID_OPERATION = -ENOSYS, + BAD_VALUE = -EINVAL, + BAD_TYPE = (UNKNOWN_ERROR + 1), + NAME_NOT_FOUND = -ENOENT, + PERMISSION_DENIED = -EPERM, + NO_INIT = -ENODEV, + ALREADY_EXISTS = -EEXIST, + DEAD_OBJECT = -EPIPE, + FAILED_TRANSACTION = (UNKNOWN_ERROR + 2), + BAD_INDEX = -E2BIG, + NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3), + WOULD_BLOCK = (UNKNOWN_ERROR + 4), + TIMED_OUT = (UNKNOWN_ERROR + 5), + UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6), + FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7), }; class NativeGraphicBufferInterface { - public: - enum { - USAGE_SW_READ_NEVER = 0x00000000, - USAGE_SW_READ_RARELY = 0x00000002, - USAGE_SW_READ_OFTEN = 0x00000003, - USAGE_SW_READ_MASK = 0x0000000f, +public: + enum { + USAGE_SW_READ_NEVER = 0x00000000, + USAGE_SW_READ_RARELY = 0x00000002, + USAGE_SW_READ_OFTEN = 0x00000003, + USAGE_SW_READ_MASK = 0x0000000f, - USAGE_SW_WRITE_NEVER = 0x00000000, - USAGE_SW_WRITE_RARELY = 0x00000020, - USAGE_SW_WRITE_OFTEN = 0x00000030, - USAGE_SW_WRITE_MASK = 0x000000f0, + USAGE_SW_WRITE_NEVER = 0x00000000, + USAGE_SW_WRITE_RARELY = 0x00000020, + USAGE_SW_WRITE_OFTEN = 0x00000030, + USAGE_SW_WRITE_MASK = 0x000000f0, - USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK, + USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK, - USAGE_PROTECTED = 0x00004000, + USAGE_PROTECTED = 0x00004000, - USAGE_HW_TEXTURE = 0x00000100, - USAGE_HW_RENDER = 0x00000200, - USAGE_HW_2D = 0x00000400, - USAGE_HW_COMPOSER = 0x00000800, - USAGE_HW_VIDEO_ENCODER = 0x00010000, - USAGE_HW_MASK = 0x00071F00, - }; + USAGE_HW_TEXTURE = 0x00000100, + USAGE_HW_RENDER = 0x00000200, + USAGE_HW_2D = 0x00000400, + USAGE_HW_COMPOSER = 0x00000800, + USAGE_HW_VIDEO_ENCODER = 0x00010000, + USAGE_HW_MASK = 0x00071F00, + }; - static NativeGraphicBufferInterface* Get(); - NativeGraphicBufferInterface(); - ~NativeGraphicBufferInterface(); - NativeGraphicBufferInterface(const NativeGraphicBufferInterface&) = delete; - NativeGraphicBufferInterface& operator=(const NativeGraphicBufferInterface&) = delete; - static android::GraphicBuffer* MakeGraphicBuffer(uint32_t width, uint32_t height, - PixelFormat format, uint32_t usage); - void (*constructor)(); - void (*destructor)(); - status_t (*initCheck)(android::GraphicBuffer* buffer); - status_t (*lock)(android::GraphicBuffer* buffer, uint32_t usage, void** vaddr); - status_t (*unlock)(android::GraphicBuffer* buffer); - ANativeWindowBuffer* (*getNativeBuffer)(const android::GraphicBuffer* buffer); - static android::android_native_base_t* GetAndroidNativeBase(const android::GraphicBuffer* buffer); - static void Acquire(android::GraphicBuffer* buffer); - static void Release(android::GraphicBuffer* buffer); + static NativeGraphicBufferInterface* Get(); + NativeGraphicBufferInterface(); + ~NativeGraphicBufferInterface(); + NativeGraphicBufferInterface(const NativeGraphicBufferInterface&) = delete; + NativeGraphicBufferInterface& operator=(const NativeGraphicBufferInterface&) = delete; + static android::GraphicBuffer* MakeGraphicBuffer(uint32_t width, uint32_t height, + PixelFormat format, uint32_t usage); + void (*constructor)(); + void (*destructor)(); + status_t (*initCheck)(android::GraphicBuffer* buffer); + status_t (*lock)(android::GraphicBuffer* buffer, uint32_t usage, void** vaddr); + status_t (*unlock)(android::GraphicBuffer* buffer); + ANativeWindowBuffer* (*getNativeBuffer)(const android::GraphicBuffer* buffer); + static android::android_native_base_t* GetAndroidNativeBase(const android::GraphicBuffer* buffer); + static void Acquire(android::GraphicBuffer* buffer); + static void Release(android::GraphicBuffer* buffer); - private: - void* libHandle = nullptr; +private: + void* libHandle = nullptr; }; } // namespace pag diff --git a/src/platform/android/NativeHardwareBuffer.cpp b/src/platform/android/NativeHardwareBuffer.cpp index 48bd330747..81677bf5be 100644 --- a/src/platform/android/NativeHardwareBuffer.cpp +++ b/src/platform/android/NativeHardwareBuffer.cpp @@ -32,66 +32,67 @@ namespace pag { std::shared_ptr NativeHardwareBuffer::MakeAdopted( AHardwareBuffer* hardwareBuffer) { - if (!hardwareBuffer || !NativeHardwareBufferInterface::Get()->AHardwareBuffer_allocate) { - return nullptr; - } - return std::shared_ptr(new NativeHardwareBuffer(hardwareBuffer)); + if (!hardwareBuffer || !NativeHardwareBufferInterface::Get()->AHardwareBuffer_allocate) { + return nullptr; + } + return std::shared_ptr(new NativeHardwareBuffer(hardwareBuffer)); } std::shared_ptr NativeHardwareBuffer::Make(int width, int height, bool alphaOnly) { - auto interface = NativeHardwareBufferInterface::Get(); - if (alphaOnly || !interface->AHardwareBuffer_allocate) { - return nullptr; - } - AHardwareBuffer* buffer = nullptr; - AHardwareBuffer_Desc desc = { - static_cast(width), - static_cast(height), - 1, - AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, - AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | - AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT, - 0, - 0, - 0}; - interface->AHardwareBuffer_allocate(&desc, &buffer); - if (!buffer) { - return nullptr; - } - auto hardwareBuffer = std::shared_ptr(new NativeHardwareBuffer(buffer)); - interface->AHardwareBuffer_release(buffer); - return hardwareBuffer; + auto interface = NativeHardwareBufferInterface::Get(); + if (alphaOnly || !interface->AHardwareBuffer_allocate) { + return nullptr; + } + AHardwareBuffer* buffer = nullptr; + AHardwareBuffer_Desc desc = { + static_cast(width), + static_cast(height), + 1, + AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, + AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | + AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT, + 0, + 0, + 0 + }; + interface->AHardwareBuffer_allocate(&desc, &buffer); + if (!buffer) { + return nullptr; + } + auto hardwareBuffer = std::shared_ptr(new NativeHardwareBuffer(buffer)); + interface->AHardwareBuffer_release(buffer); + return hardwareBuffer; } static ImageInfo GetImageInfo(AHardwareBuffer* hardwareBuffer) { - AHardwareBuffer_Desc desc; - NativeHardwareBufferInterface::Get()->AHardwareBuffer_describe(hardwareBuffer, &desc); - return ImageInfo::Make(desc.width, desc.height, ColorType::RGBA_8888, AlphaType::Premultiplied, - desc.stride * 4); + AHardwareBuffer_Desc desc; + NativeHardwareBufferInterface::Get()->AHardwareBuffer_describe(hardwareBuffer, &desc); + return ImageInfo::Make(desc.width, desc.height, ColorType::RGBA_8888, AlphaType::Premultiplied, + desc.stride * 4); } NativeHardwareBuffer::NativeHardwareBuffer(AHardwareBuffer* hardwareBuffer) : PixelBuffer(GetImageInfo(hardwareBuffer)), hardwareBuffer(hardwareBuffer) { - NativeHardwareBufferInterface::Get()->AHardwareBuffer_acquire(hardwareBuffer); + NativeHardwareBufferInterface::Get()->AHardwareBuffer_acquire(hardwareBuffer); } std::shared_ptr NativeHardwareBuffer::makeTexture(Context* context) const { - return GLHardwareTexture::MakeFrom(context, hardwareBuffer); + return GLHardwareTexture::MakeFrom(context, hardwareBuffer); } void* NativeHardwareBuffer::lockPixels() { - uint8_t* readPtr = nullptr; - NativeHardwareBufferInterface::Get()->AHardwareBuffer_lock( - hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, - -1, nullptr, reinterpret_cast(&readPtr)); - return readPtr; + uint8_t* readPtr = nullptr; + NativeHardwareBufferInterface::Get()->AHardwareBuffer_lock( + hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, + -1, nullptr, reinterpret_cast(&readPtr)); + return readPtr; } void NativeHardwareBuffer::unlockPixels() { - NativeHardwareBufferInterface::Get()->AHardwareBuffer_unlock(hardwareBuffer, nullptr); + NativeHardwareBufferInterface::Get()->AHardwareBuffer_unlock(hardwareBuffer, nullptr); } NativeHardwareBuffer::~NativeHardwareBuffer() { - NativeHardwareBufferInterface::Get()->AHardwareBuffer_release(hardwareBuffer); + NativeHardwareBufferInterface::Get()->AHardwareBuffer_release(hardwareBuffer); } } // namespace pag diff --git a/src/platform/android/NativeHardwareBuffer.h b/src/platform/android/NativeHardwareBuffer.h index 40571f380d..2dcd69f232 100644 --- a/src/platform/android/NativeHardwareBuffer.h +++ b/src/platform/android/NativeHardwareBuffer.h @@ -24,22 +24,22 @@ namespace pag { class NativeHardwareBuffer : public PixelBuffer { - public: - static std::shared_ptr Make(int width, int height, bool alphaOnly); +public: + static std::shared_ptr Make(int width, int height, bool alphaOnly); - static std::shared_ptr MakeAdopted(AHardwareBuffer* hardwareBuffer); + static std::shared_ptr MakeAdopted(AHardwareBuffer* hardwareBuffer); - ~NativeHardwareBuffer() override; + ~NativeHardwareBuffer() override; - void* lockPixels() override; + void* lockPixels() override; - void unlockPixels() override; + void unlockPixels() override; - std::shared_ptr makeTexture(Context*) const override; + std::shared_ptr makeTexture(Context*) const override; - NativeHardwareBuffer(AHardwareBuffer* hardwareBuffer); + NativeHardwareBuffer(AHardwareBuffer* hardwareBuffer); - private: - AHardwareBuffer* hardwareBuffer = nullptr; +private: + AHardwareBuffer* hardwareBuffer = nullptr; }; } // namespace pag diff --git a/src/platform/android/NativeHardwareBufferInterface.cpp b/src/platform/android/NativeHardwareBufferInterface.cpp index d0d78a8712..b525819719 100644 --- a/src/platform/android/NativeHardwareBufferInterface.cpp +++ b/src/platform/android/NativeHardwareBufferInterface.cpp @@ -25,25 +25,25 @@ namespace pag { template static void loadSymbol(T*& pfn, const char* symbol) { - pfn = (T*)dlsym(RTLD_DEFAULT, symbol); + pfn = (T*)dlsym(RTLD_DEFAULT, symbol); } NativeHardwareBufferInterface::NativeHardwareBufferInterface() { - // if we compile for API 26 (Oreo) and above, we're guaranteed to have AHardwareBuffer - // in all other cases, we need to get them at runtime. + // if we compile for API 26 (Oreo) and above, we're guaranteed to have AHardwareBuffer + // in all other cases, we need to get them at runtime. #ifndef PLATFORM_HAS_HARDWAREBUFFER - loadSymbol(AHardwareBuffer_allocate, "AHardwareBuffer_allocate"); - loadSymbol(AHardwareBuffer_release, "AHardwareBuffer_release"); - loadSymbol(AHardwareBuffer_lock, "AHardwareBuffer_lock"); - loadSymbol(AHardwareBuffer_unlock, "AHardwareBuffer_unlock"); - loadSymbol(AHardwareBuffer_describe, "AHardwareBuffer_describe"); - loadSymbol(AHardwareBuffer_acquire, "AHardwareBuffer_acquire"); + loadSymbol(AHardwareBuffer_allocate, "AHardwareBuffer_allocate"); + loadSymbol(AHardwareBuffer_release, "AHardwareBuffer_release"); + loadSymbol(AHardwareBuffer_lock, "AHardwareBuffer_lock"); + loadSymbol(AHardwareBuffer_unlock, "AHardwareBuffer_unlock"); + loadSymbol(AHardwareBuffer_describe, "AHardwareBuffer_describe"); + loadSymbol(AHardwareBuffer_acquire, "AHardwareBuffer_acquire"); #endif } NativeHardwareBufferInterface* NativeHardwareBufferInterface::Get() { - static NativeHardwareBufferInterface instance; - return &instance; + static NativeHardwareBufferInterface instance; + return &instance; } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/NativeHardwareBufferInterface.h b/src/platform/android/NativeHardwareBufferInterface.h index 13999230dc..f8648b2bec 100644 --- a/src/platform/android/NativeHardwareBufferInterface.h +++ b/src/platform/android/NativeHardwareBufferInterface.h @@ -28,23 +28,23 @@ namespace pag { class NativeHardwareBufferInterface { - public: - static NativeHardwareBufferInterface* Get(); - NativeHardwareBufferInterface(const NativeHardwareBufferInterface&) = delete; - NativeHardwareBufferInterface& operator=(const NativeHardwareBufferInterface&) = delete; +public: + static NativeHardwareBufferInterface* Get(); + NativeHardwareBufferInterface(const NativeHardwareBufferInterface&) = delete; + NativeHardwareBufferInterface& operator=(const NativeHardwareBufferInterface&) = delete; #ifndef PLATFORM_HAS_HARDWAREBUFFER - // if we compile for API 26 (Oreo) and above, we're guaranteed to have AHardwareBuffer - // in all other cases, we need to get them at runtime. - int (*AHardwareBuffer_allocate)(const AHardwareBuffer_Desc*, AHardwareBuffer**) = nullptr; - void (*AHardwareBuffer_release)(AHardwareBuffer*) = nullptr; - int (*AHardwareBuffer_lock)(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, - const ARect* rect, void** outVirtualAddress) = nullptr; - int (*AHardwareBuffer_unlock)(AHardwareBuffer* buffer, int32_t* fence) = nullptr; - void (*AHardwareBuffer_describe)(const AHardwareBuffer* buffer, - AHardwareBuffer_Desc* outDesc) = nullptr; - void (*AHardwareBuffer_acquire)(AHardwareBuffer* buffer) = nullptr; + // if we compile for API 26 (Oreo) and above, we're guaranteed to have AHardwareBuffer + // in all other cases, we need to get them at runtime. + int (*AHardwareBuffer_allocate)(const AHardwareBuffer_Desc*, AHardwareBuffer**) = nullptr; + void (*AHardwareBuffer_release)(AHardwareBuffer*) = nullptr; + int (*AHardwareBuffer_lock)(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, + const ARect* rect, void** outVirtualAddress) = nullptr; + int (*AHardwareBuffer_unlock)(AHardwareBuffer* buffer, int32_t* fence) = nullptr; + void (*AHardwareBuffer_describe)(const AHardwareBuffer* buffer, + AHardwareBuffer_Desc* outDesc) = nullptr; + void (*AHardwareBuffer_acquire)(AHardwareBuffer* buffer) = nullptr; #endif - private: - NativeHardwareBufferInterface(); +private: + NativeHardwareBufferInterface(); }; } // namespace pag diff --git a/src/platform/android/NativeImage.cpp b/src/platform/android/NativeImage.cpp index 18b986bbb9..4aca408f87 100644 --- a/src/platform/android/NativeImage.cpp +++ b/src/platform/android/NativeImage.cpp @@ -37,125 +37,125 @@ static jmethodID ImageCodec_CreateBitmapFromPath; static jmethodID ImageCodec_CreateBitmapFromBytes; void NativeImage::InitJNI(JNIEnv* env) { - ImageCodecClass.reset(env, env->FindClass("org/libpag/ImageCodec")); - ImageCodec_GetSizeFromPath = - env->GetStaticMethodID(ImageCodecClass.get(), "GetSizeFromPath", "(Ljava/lang/String;)[I"); - ImageCodec_GetSizeFromBytes = env->GetStaticMethodID(ImageCodecClass.get(), "GetSizeFromBytes", - "(Ljava/nio/ByteBuffer;)[I"); - ImageCodec_GetOrientationFromPath = env->GetStaticMethodID( - ImageCodecClass.get(), "GetOrientationFromPath", "(Ljava/lang/String;)I"); - ImageCodec_GetOrientationFromBytes = env->GetStaticMethodID( - ImageCodecClass.get(), "GetOrientationFromBytes", "(Ljava/nio/ByteBuffer;)I"); - ImageCodec_CreateBitmapFromPath = - env->GetStaticMethodID(ImageCodecClass.get(), "CreateBitmapFromPath", - "(Ljava/lang/String;I)Landroid/graphics/Bitmap;"); - ImageCodec_CreateBitmapFromBytes = - env->GetStaticMethodID(ImageCodecClass.get(), "CreateBitmapFromBytes", - "(Ljava/nio/ByteBuffer;I)Landroid/graphics/Bitmap;"); + ImageCodecClass.reset(env, env->FindClass("org/libpag/ImageCodec")); + ImageCodec_GetSizeFromPath = + env->GetStaticMethodID(ImageCodecClass.get(), "GetSizeFromPath", "(Ljava/lang/String;)[I"); + ImageCodec_GetSizeFromBytes = env->GetStaticMethodID(ImageCodecClass.get(), "GetSizeFromBytes", + "(Ljava/nio/ByteBuffer;)[I"); + ImageCodec_GetOrientationFromPath = env->GetStaticMethodID( + ImageCodecClass.get(), "GetOrientationFromPath", "(Ljava/lang/String;)I"); + ImageCodec_GetOrientationFromBytes = env->GetStaticMethodID( + ImageCodecClass.get(), "GetOrientationFromBytes", "(Ljava/nio/ByteBuffer;)I"); + ImageCodec_CreateBitmapFromPath = + env->GetStaticMethodID(ImageCodecClass.get(), "CreateBitmapFromPath", + "(Ljava/lang/String;I)Landroid/graphics/Bitmap;"); + ImageCodec_CreateBitmapFromBytes = + env->GetStaticMethodID(ImageCodecClass.get(), "CreateBitmapFromBytes", + "(Ljava/nio/ByteBuffer;I)Landroid/graphics/Bitmap;"); } std::shared_ptr NativeImage::Make(JNIEnv* env, jobject sizeObject, int orientation) { - auto size = env->GetIntArrayElements(static_cast(sizeObject), nullptr); - int width = size[0]; - int height = size[1]; - env->ReleaseIntArrayElements(static_cast(sizeObject), size, 0); - if (width <= 0 || height <= 0) { - return nullptr; - } - return std::unique_ptr( - new NativeImage(width, height, static_cast(orientation))); + auto size = env->GetIntArrayElements(static_cast(sizeObject), nullptr); + int width = size[0]; + int height = size[1]; + env->ReleaseIntArrayElements(static_cast(sizeObject), size, 0); + if (width <= 0 || height <= 0) { + return nullptr; + } + return std::unique_ptr( + new NativeImage(width, height, static_cast(orientation))); } std::shared_ptr NativeImage::MakeFrom(const std::string& filePath) { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return nullptr; - } - jstring imagePath = SafeConvertToJString(env, filePath.c_str()); - auto sizeObject = - env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_GetSizeFromPath, imagePath); - auto orientation = - env->CallStaticIntMethod(ImageCodecClass.get(), ImageCodec_GetOrientationFromPath, imagePath); - auto image = Make(env, sizeObject, orientation); - if (image != nullptr) { - image->imagePath = filePath; - } - env->DeleteLocalRef(sizeObject); - env->DeleteLocalRef(imagePath); - return image; + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return nullptr; + } + jstring imagePath = SafeConvertToJString(env, filePath.c_str()); + auto sizeObject = + env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_GetSizeFromPath, imagePath); + auto orientation = + env->CallStaticIntMethod(ImageCodecClass.get(), ImageCodec_GetOrientationFromPath, imagePath); + auto image = Make(env, sizeObject, orientation); + if (image != nullptr) { + image->imagePath = filePath; + } + env->DeleteLocalRef(sizeObject); + env->DeleteLocalRef(imagePath); + return image; } std::shared_ptr NativeImage::MakeFrom(std::shared_ptr imageBytes) { - auto env = JNIEnvironment::Current(); - if (env == nullptr || imageBytes == nullptr) { - return nullptr; - } - auto byteBuffer = - env->NewDirectByteBuffer(const_cast(imageBytes->data()), imageBytes->size()); - auto sizeObject = - env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_GetSizeFromBytes, byteBuffer); - auto orientation = env->CallStaticIntMethod(ImageCodecClass.get(), - ImageCodec_GetOrientationFromBytes, byteBuffer); - auto image = Make(env, sizeObject, orientation); - if (image != nullptr) { - image->imageBytes = imageBytes; - } - env->DeleteLocalRef(sizeObject); - env->DeleteLocalRef(byteBuffer); - return image; + auto env = JNIEnvironment::Current(); + if (env == nullptr || imageBytes == nullptr) { + return nullptr; + } + auto byteBuffer = + env->NewDirectByteBuffer(const_cast(imageBytes->data()), imageBytes->size()); + auto sizeObject = + env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_GetSizeFromBytes, byteBuffer); + auto orientation = env->CallStaticIntMethod(ImageCodecClass.get(), + ImageCodec_GetOrientationFromBytes, byteBuffer); + auto image = Make(env, sizeObject, orientation); + if (image != nullptr) { + image->imageBytes = imageBytes; + } + env->DeleteLocalRef(sizeObject); + env->DeleteLocalRef(byteBuffer); + return image; } bool NativeImage::readPixels(const ImageInfo& dstInfo, void* dstPixels) const { - if (dstInfo.isEmpty() || dstPixels == nullptr) { - return false; - } - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - int androidColorType = 0; - switch (dstInfo.colorType()) { + if (dstInfo.isEmpty() || dstPixels == nullptr) { + return false; + } + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return false; + } + int androidColorType = 0; + switch (dstInfo.colorType()) { case ColorType::RGBA_8888: - androidColorType = dstInfo.alphaType() == AlphaType::Premultiplied - ? COLOR_TYPE_ARGB_8888_PREMULTIPLIED - : COLOR_TYPE_ARGB_8888_UNPREMULTIPLIED; - break; + androidColorType = dstInfo.alphaType() == AlphaType::Premultiplied + ? COLOR_TYPE_ARGB_8888_PREMULTIPLIED + : COLOR_TYPE_ARGB_8888_UNPREMULTIPLIED; + break; case ColorType::ALPHA_8: - androidColorType = COLOR_TYPE_ALPHA_8; - break; + androidColorType = COLOR_TYPE_ALPHA_8; + break; default: - break; - } - if (androidColorType == 0) { - return false; - } - jobject bitmap = NULL; - if (!imagePath.empty()) { - jstring path = SafeConvertToJString(env, imagePath.c_str()); - bitmap = env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_CreateBitmapFromPath, - path, androidColorType); - env->DeleteLocalRef(path); - } else { - auto byteBuffer = - env->NewDirectByteBuffer(const_cast(imageBytes->data()), imageBytes->size()); - bitmap = env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_CreateBitmapFromBytes, - byteBuffer, androidColorType); - env->DeleteLocalRef(byteBuffer); - } - auto info = GetImageInfo(env, bitmap); - if (info.isEmpty()) { - env->DeleteLocalRef(bitmap); - return false; - } - void* pixels = nullptr; - if (AndroidBitmap_lockPixels(env, bitmap, &pixels) != 0) { + break; + } + if (androidColorType == 0) { + return false; + } + jobject bitmap = NULL; + if (!imagePath.empty()) { + jstring path = SafeConvertToJString(env, imagePath.c_str()); + bitmap = env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_CreateBitmapFromPath, + path, androidColorType); + env->DeleteLocalRef(path); + } else { + auto byteBuffer = + env->NewDirectByteBuffer(const_cast(imageBytes->data()), imageBytes->size()); + bitmap = env->CallStaticObjectMethod(ImageCodecClass.get(), ImageCodec_CreateBitmapFromBytes, + byteBuffer, androidColorType); + env->DeleteLocalRef(byteBuffer); + } + auto info = GetImageInfo(env, bitmap); + if (info.isEmpty()) { + env->DeleteLocalRef(bitmap); + return false; + } + void* pixels = nullptr; + if (AndroidBitmap_lockPixels(env, bitmap, &pixels) != 0) { + env->DeleteLocalRef(bitmap); + return false; + } + PixelMap pixelMap(info, pixels); + auto result = pixelMap.readPixels(dstInfo, dstPixels); + AndroidBitmap_unlockPixels(env, bitmap); env->DeleteLocalRef(bitmap); - return false; - } - PixelMap pixelMap(info, pixels); - auto result = pixelMap.readPixels(dstInfo, dstPixels); - AndroidBitmap_unlockPixels(env, bitmap); - env->DeleteLocalRef(bitmap); - return result; + return result; } } // namespace pag diff --git a/src/platform/android/NativeImage.h b/src/platform/android/NativeImage.h index b47946f062..d010e87593 100644 --- a/src/platform/android/NativeImage.h +++ b/src/platform/android/NativeImage.h @@ -24,22 +24,22 @@ namespace pag { class NativeImage : public Image { - public: - static void InitJNI(JNIEnv* env); +public: + static void InitJNI(JNIEnv* env); - static std::shared_ptr MakeFrom(const std::string& filePath); + static std::shared_ptr MakeFrom(const std::string& filePath); - static std::shared_ptr MakeFrom(std::shared_ptr imageBytes); + static std::shared_ptr MakeFrom(std::shared_ptr imageBytes); - bool readPixels(const ImageInfo& dstInfo, void* dstPixels) const override; + bool readPixels(const ImageInfo& dstInfo, void* dstPixels) const override; - private: - std::string imagePath; - std::shared_ptr imageBytes; +private: + std::string imagePath; + std::shared_ptr imageBytes; - NativeImage(int width, int height, Orientation orientation) : Image(width, height, - orientation) {}; + NativeImage(int width, int height, Orientation orientation) : Image(width, height, + orientation) {}; - static std::shared_ptr Make(JNIEnv* env, jobject sizeObject, int orientation); + static std::shared_ptr Make(JNIEnv* env, jobject sizeObject, int orientation); }; } // namespace pag diff --git a/src/platform/android/NativePlatform.cpp b/src/platform/android/NativePlatform.cpp index e4b54f65fe..b48bc1c897 100644 --- a/src/platform/android/NativePlatform.cpp +++ b/src/platform/android/NativePlatform.cpp @@ -36,65 +36,65 @@ namespace pag { const Platform* Platform::Current() { - static const NativePlatform platform = {}; - return &platform; + static const NativePlatform platform = {}; + return &platform; } void NativePlatform::InitJNI(JNIEnv* env) { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - JTraceImage::InitJNI(env); - NativeImage::InitJNI(env); - FontConfigAndroid::InitJNI(env); - GPUDecoder::InitJNI(env, "org/libpag/GPUDecoder"); - VideoSurface::InitJNI(env, "org/libpag/VideoSurface"); + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + JTraceImage::InitJNI(env); + NativeImage::InitJNI(env); + FontConfigAndroid::InitJNI(env); + GPUDecoder::InitJNI(env, "org/libpag/GPUDecoder"); + VideoSurface::InitJNI(env, "org/libpag/VideoSurface"); } std::unique_ptr NativePlatform::makeHardwareDecoder( const pag::VideoConfig& config) const { - auto decoder = new GPUDecoder(config); - if (!decoder->isValid()) { - delete decoder; - return nullptr; - } - return std::unique_ptr(decoder); + auto decoder = new GPUDecoder(config); + if (!decoder->isValid()) { + delete decoder; + return nullptr; + } + return std::unique_ptr(decoder); } std::shared_ptr NativePlatform::makeImage(const std::string& filePath) const { - return NativeImage::MakeFrom(filePath); + return NativeImage::MakeFrom(filePath); } std::shared_ptr NativePlatform::makeImage(std::shared_ptr imageBytes) const { - return NativeImage::MakeFrom(imageBytes); + return NativeImage::MakeFrom(imageBytes); } PAGFont NativePlatform::parseFont(const std::string& fontPath, int ttcIndex) const { - return FontConfigAndroid::Parse(fontPath, ttcIndex); + return FontConfigAndroid::Parse(fontPath, ttcIndex); } PAGFont NativePlatform::parseFont(const void* data, size_t length, int ttcIndex) const { - return FontConfigAndroid::Parse(data, length, ttcIndex); + return FontConfigAndroid::Parse(data, length, ttcIndex); } void NativePlatform::printLog(const char* format, ...) const { - va_list args; - va_start(args, format); - __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); - va_end(args); + va_list args; + va_start(args, format); + __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); + va_end(args); } void NativePlatform::printError(const char* format, ...) const { - va_list args; - va_start(args, format); - __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); - va_end(args); + va_list args; + va_start(args, format); + __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); + va_end(args); } bool NativePlatform::registerFallbackFonts() const { - return FontConfigAndroid::RegisterFallbackFonts(); + return FontConfigAndroid::RegisterFallbackFonts(); } void NativePlatform::reportStatisticalData( @@ -102,24 +102,24 @@ void NativePlatform::reportStatisticalData( } void NativePlatform::traceImage(const pag::PixelMap& pixelMap, const std::string& tag) const { - JTraceImage::Trace(pixelMap, tag); + JTraceImage::Trace(pixelMap, tag); } static int GetSDKVersion() { - char sdk[PROP_VALUE_MAX] = "0"; - __system_property_get("ro.build.version.sdk", sdk); - return atoi(sdk); + char sdk[PROP_VALUE_MAX] = "0"; + __system_property_get("ro.build.version.sdk", sdk); + return atoi(sdk); } std::shared_ptr NativePlatform::makeHardwareBuffer(int width, int height, - bool alphaOnly) const { - static auto version = GetSDKVersion(); - if (version >= 26) { - return NativeHardwareBuffer::Make(width, height, alphaOnly); - } else if (version <= 23) { - return NativeGraphicBuffer::Make(width, height, alphaOnly); - } - return nullptr; + bool alphaOnly) const { + static auto version = GetSDKVersion(); + if (version >= 26) { + return NativeHardwareBuffer::Make(width, height, alphaOnly); + } else if (version <= 23) { + return NativeGraphicBuffer::Make(width, height, alphaOnly); + } + return nullptr; } } // namespace pag \ No newline at end of file diff --git a/src/platform/android/NativePlatform.h b/src/platform/android/NativePlatform.h index ec85842f54..113200e81a 100644 --- a/src/platform/android/NativePlatform.h +++ b/src/platform/android/NativePlatform.h @@ -23,35 +23,35 @@ namespace pag { class NativePlatform : public Platform { - public: - static void InitJNI(JNIEnv* env); +public: + static void InitJNI(JNIEnv* env); - bool hasHardwareDecoder() const override { - return true; - } + bool hasHardwareDecoder() const override { + return true; + } - std::shared_ptr makeHardwareBuffer(int width, int height, - bool alphaOnly) const override; + std::shared_ptr makeHardwareBuffer(int width, int height, + bool alphaOnly) const override; - std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; + std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; - std::shared_ptr makeImage(const std::string& filePath) const override; + std::shared_ptr makeImage(const std::string& filePath) const override; - std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; + std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; - PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; + PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; - PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; + PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; - void printLog(const char format[], ...) const override; + void printLog(const char format[], ...) const override; - void printError(const char format[], ...) const override; + void printError(const char format[], ...) const override; - bool registerFallbackFonts() const override; + bool registerFallbackFonts() const override; - void reportStatisticalData( - std::unordered_map& reportMap) const override; + void reportStatisticalData( + std::unordered_map& reportMap) const override; - void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; + void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; }; } // namespace pag diff --git a/src/platform/android/PAGText.cpp b/src/platform/android/PAGText.cpp index e7d3d79033..19f5bb5cff 100644 --- a/src/platform/android/PAGText.cpp +++ b/src/platform/android/PAGText.cpp @@ -47,128 +47,128 @@ static jfieldID PAGText_backgroundAlpha; } // namespace pag void InitPAGText(JNIEnv* env) { - PAGTextClass.reset(env, env->FindClass("org/libpag/PAGText")); - PAGTextConstructID = env->GetMethodID(PAGTextClass.get(), "", "()V"); - PAGText_applyFill = env->GetFieldID(PAGTextClass.get(), "applyFill", "Z"); - PAGText_applyStroke = env->GetFieldID(PAGTextClass.get(), "applyStroke", "Z"); - PAGText_baselineShift = env->GetFieldID(PAGTextClass.get(), "baselineShift", "F"); - PAGText_boxText = env->GetFieldID(PAGTextClass.get(), "boxText", "Z"); - PAGText_boxTextRect = - env->GetFieldID(PAGTextClass.get(), "boxTextRect", "Landroid/graphics/RectF;"); - PAGText_firstBaseLine = env->GetFieldID(PAGTextClass.get(), "firstBaseLine", "F"); - PAGText_fauxBold = env->GetFieldID(PAGTextClass.get(), "fauxBold", "Z"); - PAGText_fauxItalic = env->GetFieldID(PAGTextClass.get(), "fauxItalic", "Z"); - PAGText_fillColor = env->GetFieldID(PAGTextClass.get(), "fillColor", "I"); - PAGText_fontFamily = env->GetFieldID(PAGTextClass.get(), "fontFamily", "Ljava/lang/String;"); - PAGText_fontStyle = env->GetFieldID(PAGTextClass.get(), "fontStyle", "Ljava/lang/String;"); - PAGText_fontSize = env->GetFieldID(PAGTextClass.get(), "fontSize", "F"); - PAGText_strokeColor = env->GetFieldID(PAGTextClass.get(), "strokeColor", "I"); - PAGText_strokeOverFill = env->GetFieldID(PAGTextClass.get(), "strokeOverFill", "Z"); - PAGText_strokeWidth = env->GetFieldID(PAGTextClass.get(), "strokeWidth", "F"); - PAGText_text = env->GetFieldID(PAGTextClass.get(), "text", "Ljava/lang/String;"); - PAGText_justification = env->GetFieldID(PAGTextClass.get(), "justification", "I"); - PAGText_leading = env->GetFieldID(PAGTextClass.get(), "leading", "F"); - PAGText_tracking = env->GetFieldID(PAGTextClass.get(), "tracking", "F"); - PAGText_backgroundColor = env->GetFieldID(PAGTextClass.get(), "backgroundColor", "I"); - PAGText_backgroundAlpha = env->GetFieldID(PAGTextClass.get(), "backgroundAlpha", "I"); + PAGTextClass.reset(env, env->FindClass("org/libpag/PAGText")); + PAGTextConstructID = env->GetMethodID(PAGTextClass.get(), "", "()V"); + PAGText_applyFill = env->GetFieldID(PAGTextClass.get(), "applyFill", "Z"); + PAGText_applyStroke = env->GetFieldID(PAGTextClass.get(), "applyStroke", "Z"); + PAGText_baselineShift = env->GetFieldID(PAGTextClass.get(), "baselineShift", "F"); + PAGText_boxText = env->GetFieldID(PAGTextClass.get(), "boxText", "Z"); + PAGText_boxTextRect = + env->GetFieldID(PAGTextClass.get(), "boxTextRect", "Landroid/graphics/RectF;"); + PAGText_firstBaseLine = env->GetFieldID(PAGTextClass.get(), "firstBaseLine", "F"); + PAGText_fauxBold = env->GetFieldID(PAGTextClass.get(), "fauxBold", "Z"); + PAGText_fauxItalic = env->GetFieldID(PAGTextClass.get(), "fauxItalic", "Z"); + PAGText_fillColor = env->GetFieldID(PAGTextClass.get(), "fillColor", "I"); + PAGText_fontFamily = env->GetFieldID(PAGTextClass.get(), "fontFamily", "Ljava/lang/String;"); + PAGText_fontStyle = env->GetFieldID(PAGTextClass.get(), "fontStyle", "Ljava/lang/String;"); + PAGText_fontSize = env->GetFieldID(PAGTextClass.get(), "fontSize", "F"); + PAGText_strokeColor = env->GetFieldID(PAGTextClass.get(), "strokeColor", "I"); + PAGText_strokeOverFill = env->GetFieldID(PAGTextClass.get(), "strokeOverFill", "Z"); + PAGText_strokeWidth = env->GetFieldID(PAGTextClass.get(), "strokeWidth", "F"); + PAGText_text = env->GetFieldID(PAGTextClass.get(), "text", "Ljava/lang/String;"); + PAGText_justification = env->GetFieldID(PAGTextClass.get(), "justification", "I"); + PAGText_leading = env->GetFieldID(PAGTextClass.get(), "leading", "F"); + PAGText_tracking = env->GetFieldID(PAGTextClass.get(), "tracking", "F"); + PAGText_backgroundColor = env->GetFieldID(PAGTextClass.get(), "backgroundColor", "I"); + PAGText_backgroundAlpha = env->GetFieldID(PAGTextClass.get(), "backgroundAlpha", "I"); } jobject ToPAGTextObject(JNIEnv* env, pag::TextDocumentHandle textDocument) { - if (textDocument == nullptr) { - return nullptr; - } - if (PAGTextClass.get() == nullptr) { - InitPAGText(env); - } - auto textData = env->NewObject(PAGTextClass.get(), PAGTextConstructID); - env->SetBooleanField(textData, PAGText_applyFill, static_cast(textDocument->applyFill)); - env->SetBooleanField(textData, PAGText_applyStroke, - static_cast(textDocument->applyStroke)); - env->SetFloatField(textData, PAGText_baselineShift, textDocument->baselineShift); - env->SetBooleanField(textData, PAGText_boxText, static_cast(textDocument->boxText)); - jobject boxTextRect = MakeRectFObject(env, textDocument->boxTextPos.x, textDocument->boxTextPos.y, - textDocument->boxTextSize.x, textDocument->boxTextSize.y); - env->SetObjectField(textData, PAGText_boxTextRect, boxTextRect); - env->SetFloatField(textData, PAGText_firstBaseLine, textDocument->firstBaseLine); - env->SetBooleanField(textData, PAGText_fauxBold, static_cast(textDocument->fauxBold)); - env->SetBooleanField(textData, PAGText_fauxItalic, - static_cast(textDocument->fauxItalic)); - jint fillColor = MakeColorInt(env, textDocument->fillColor.red, textDocument->fillColor.green, - textDocument->fillColor.blue); - env->SetIntField(textData, PAGText_fillColor, fillColor); - jstring fontFamily = SafeConvertToJString(env, textDocument->fontFamily.c_str()); - env->SetObjectField(textData, PAGText_fontFamily, fontFamily); - jstring fontStyle = SafeConvertToJString(env, textDocument->fontStyle.c_str()); - env->SetObjectField(textData, PAGText_fontStyle, fontStyle); - env->SetFloatField(textData, PAGText_fontSize, textDocument->fontSize); - jint strokeColor = MakeColorInt(env, textDocument->strokeColor.red, - textDocument->strokeColor.green, textDocument->strokeColor.blue); - env->SetIntField(textData, PAGText_strokeColor, strokeColor); - env->SetBooleanField(textData, PAGText_strokeOverFill, - static_cast(textDocument->strokeOverFill)); - env->SetFloatField(textData, PAGText_strokeWidth, textDocument->strokeWidth); - jstring text = SafeConvertToJString(env, textDocument->text.c_str()); - env->SetObjectField(textData, PAGText_text, text); - env->SetIntField(textData, PAGText_justification, textDocument->justification); - env->SetFloatField(textData, PAGText_leading, textDocument->leading); - env->SetFloatField(textData, PAGText_tracking, textDocument->tracking); - jint backgroundColor = - MakeColorInt(env, textDocument->backgroundColor.red, textDocument->backgroundColor.green, - textDocument->backgroundColor.blue); - env->SetIntField(textData, PAGText_backgroundColor, backgroundColor); - env->SetIntField(textData, PAGText_backgroundAlpha, textDocument->backgroundAlpha); - env->DeleteLocalRef(fontFamily); - env->DeleteLocalRef(fontStyle); - env->DeleteLocalRef(text); - return textData; + if (textDocument == nullptr) { + return nullptr; + } + if (PAGTextClass.get() == nullptr) { + InitPAGText(env); + } + auto textData = env->NewObject(PAGTextClass.get(), PAGTextConstructID); + env->SetBooleanField(textData, PAGText_applyFill, static_cast(textDocument->applyFill)); + env->SetBooleanField(textData, PAGText_applyStroke, + static_cast(textDocument->applyStroke)); + env->SetFloatField(textData, PAGText_baselineShift, textDocument->baselineShift); + env->SetBooleanField(textData, PAGText_boxText, static_cast(textDocument->boxText)); + jobject boxTextRect = MakeRectFObject(env, textDocument->boxTextPos.x, textDocument->boxTextPos.y, + textDocument->boxTextSize.x, textDocument->boxTextSize.y); + env->SetObjectField(textData, PAGText_boxTextRect, boxTextRect); + env->SetFloatField(textData, PAGText_firstBaseLine, textDocument->firstBaseLine); + env->SetBooleanField(textData, PAGText_fauxBold, static_cast(textDocument->fauxBold)); + env->SetBooleanField(textData, PAGText_fauxItalic, + static_cast(textDocument->fauxItalic)); + jint fillColor = MakeColorInt(env, textDocument->fillColor.red, textDocument->fillColor.green, + textDocument->fillColor.blue); + env->SetIntField(textData, PAGText_fillColor, fillColor); + jstring fontFamily = SafeConvertToJString(env, textDocument->fontFamily.c_str()); + env->SetObjectField(textData, PAGText_fontFamily, fontFamily); + jstring fontStyle = SafeConvertToJString(env, textDocument->fontStyle.c_str()); + env->SetObjectField(textData, PAGText_fontStyle, fontStyle); + env->SetFloatField(textData, PAGText_fontSize, textDocument->fontSize); + jint strokeColor = MakeColorInt(env, textDocument->strokeColor.red, + textDocument->strokeColor.green, textDocument->strokeColor.blue); + env->SetIntField(textData, PAGText_strokeColor, strokeColor); + env->SetBooleanField(textData, PAGText_strokeOverFill, + static_cast(textDocument->strokeOverFill)); + env->SetFloatField(textData, PAGText_strokeWidth, textDocument->strokeWidth); + jstring text = SafeConvertToJString(env, textDocument->text.c_str()); + env->SetObjectField(textData, PAGText_text, text); + env->SetIntField(textData, PAGText_justification, textDocument->justification); + env->SetFloatField(textData, PAGText_leading, textDocument->leading); + env->SetFloatField(textData, PAGText_tracking, textDocument->tracking); + jint backgroundColor = + MakeColorInt(env, textDocument->backgroundColor.red, textDocument->backgroundColor.green, + textDocument->backgroundColor.blue); + env->SetIntField(textData, PAGText_backgroundColor, backgroundColor); + env->SetIntField(textData, PAGText_backgroundAlpha, textDocument->backgroundAlpha); + env->DeleteLocalRef(fontFamily); + env->DeleteLocalRef(fontStyle); + env->DeleteLocalRef(text); + return textData; } TextDocumentHandle ToTextDocument(JNIEnv* env, jobject textData) { - if (textData == nullptr) { - return nullptr; - } - if (PAGTextClass.get() == nullptr) { - InitPAGText(env); - } - auto textDocument = pag::TextDocumentHandle(new TextDocument()); - textDocument->applyFill = env->GetBooleanField(textData, PAGText_applyFill); - textDocument->applyStroke = env->GetBooleanField(textData, PAGText_applyStroke); - textDocument->baselineShift = env->GetFloatField(textData, PAGText_baselineShift); - textDocument->boxText = env->GetBooleanField(textData, PAGText_boxText); - jobject boxTextRect = env->GetObjectField(textData, PAGText_boxTextRect); - auto boxRect = ToRectData(env, boxTextRect); - textDocument->boxTextPos = {boxRect.x, boxRect.y}; - textDocument->boxTextSize = {boxRect.width, boxRect.height}; - textDocument->firstBaseLine = env->GetFloatField(textData, PAGText_firstBaseLine); - textDocument->fauxBold = env->GetBooleanField(textData, PAGText_fauxBold); - textDocument->fauxItalic = env->GetBooleanField(textData, PAGText_fauxItalic); - jint fillColorObject = env->GetIntField(textData, PAGText_fillColor); - textDocument->fillColor = ToColor(env, fillColorObject); - jstring fontFamilyObject = (jstring)env->GetObjectField(textData, PAGText_fontFamily); - textDocument->fontFamily = SafeConvertToStdString(env, fontFamilyObject); - ; - jstring fontStyleObject = (jstring)env->GetObjectField(textData, PAGText_fontStyle); - textDocument->fontStyle = SafeConvertToStdString(env, fontStyleObject); - ; - textDocument->fontSize = env->GetFloatField(textData, PAGText_fontSize); - jint strokeColorObject = env->GetIntField(textData, PAGText_strokeColor); - textDocument->strokeColor = ToColor(env, strokeColorObject); - textDocument->strokeOverFill = env->GetBooleanField(textData, PAGText_strokeOverFill); - textDocument->strokeWidth = env->GetFloatField(textData, PAGText_strokeWidth); - jstring textObject = (jstring)env->GetObjectField(textData, PAGText_text); - textDocument->text = SafeConvertToStdString(env, textObject); - ; - textDocument->justification = - static_cast(env->GetIntField(textData, PAGText_justification)); - textDocument->leading = env->GetFloatField(textData, PAGText_leading); - textDocument->tracking = env->GetFloatField(textData, PAGText_tracking); - jint backgroundColorObject = env->GetIntField(textData, PAGText_backgroundColor); - textDocument->backgroundColor = ToColor(env, backgroundColorObject); - jint backgroundAlphaObject = env->GetIntField(textData, PAGText_backgroundAlpha); - textDocument->backgroundAlpha = static_cast(backgroundAlphaObject); - env->DeleteLocalRef(boxTextRect); - env->DeleteLocalRef(fontFamilyObject); - env->DeleteLocalRef(fontStyleObject); - env->DeleteLocalRef(textObject); - return textDocument; + if (textData == nullptr) { + return nullptr; + } + if (PAGTextClass.get() == nullptr) { + InitPAGText(env); + } + auto textDocument = pag::TextDocumentHandle(new TextDocument()); + textDocument->applyFill = env->GetBooleanField(textData, PAGText_applyFill); + textDocument->applyStroke = env->GetBooleanField(textData, PAGText_applyStroke); + textDocument->baselineShift = env->GetFloatField(textData, PAGText_baselineShift); + textDocument->boxText = env->GetBooleanField(textData, PAGText_boxText); + jobject boxTextRect = env->GetObjectField(textData, PAGText_boxTextRect); + auto boxRect = ToRectData(env, boxTextRect); + textDocument->boxTextPos = {boxRect.x, boxRect.y}; + textDocument->boxTextSize = {boxRect.width, boxRect.height}; + textDocument->firstBaseLine = env->GetFloatField(textData, PAGText_firstBaseLine); + textDocument->fauxBold = env->GetBooleanField(textData, PAGText_fauxBold); + textDocument->fauxItalic = env->GetBooleanField(textData, PAGText_fauxItalic); + jint fillColorObject = env->GetIntField(textData, PAGText_fillColor); + textDocument->fillColor = ToColor(env, fillColorObject); + jstring fontFamilyObject = (jstring)env->GetObjectField(textData, PAGText_fontFamily); + textDocument->fontFamily = SafeConvertToStdString(env, fontFamilyObject); + ; + jstring fontStyleObject = (jstring)env->GetObjectField(textData, PAGText_fontStyle); + textDocument->fontStyle = SafeConvertToStdString(env, fontStyleObject); + ; + textDocument->fontSize = env->GetFloatField(textData, PAGText_fontSize); + jint strokeColorObject = env->GetIntField(textData, PAGText_strokeColor); + textDocument->strokeColor = ToColor(env, strokeColorObject); + textDocument->strokeOverFill = env->GetBooleanField(textData, PAGText_strokeOverFill); + textDocument->strokeWidth = env->GetFloatField(textData, PAGText_strokeWidth); + jstring textObject = (jstring)env->GetObjectField(textData, PAGText_text); + textDocument->text = SafeConvertToStdString(env, textObject); + ; + textDocument->justification = + static_cast(env->GetIntField(textData, PAGText_justification)); + textDocument->leading = env->GetFloatField(textData, PAGText_leading); + textDocument->tracking = env->GetFloatField(textData, PAGText_tracking); + jint backgroundColorObject = env->GetIntField(textData, PAGText_backgroundColor); + textDocument->backgroundColor = ToColor(env, backgroundColorObject); + jint backgroundAlphaObject = env->GetIntField(textData, PAGText_backgroundAlpha); + textDocument->backgroundAlpha = static_cast(backgroundAlphaObject); + env->DeleteLocalRef(boxTextRect); + env->DeleteLocalRef(fontFamilyObject); + env->DeleteLocalRef(fontStyleObject); + env->DeleteLocalRef(textObject); + return textDocument; } \ No newline at end of file diff --git a/src/platform/android/VideoImage.cpp b/src/platform/android/VideoImage.cpp index 6f641ef2c8..6ea8017eae 100644 --- a/src/platform/android/VideoImage.cpp +++ b/src/platform/android/VideoImage.cpp @@ -20,13 +20,13 @@ namespace pag { std::shared_ptr VideoImage::MakeFrom(std::shared_ptr videoSurface, - int width, int height) { - if (videoSurface == nullptr) { - return nullptr; - } - auto videoImage = - std::shared_ptr(new VideoImage(std::move(videoSurface), width, height)); - return videoImage; + int width, int height) { + if (videoSurface == nullptr) { + return nullptr; + } + auto videoImage = + std::shared_ptr(new VideoImage(std::move(videoSurface), width, height)); + return videoImage; } VideoImage::VideoImage(std::shared_ptr videoSurface, int width, int height) @@ -35,13 +35,13 @@ VideoImage::VideoImage(std::shared_ptr videoSurface, int width, in } std::shared_ptr VideoImage::makeTexture(Context* context) const { - std::lock_guard autoLock(locker); - if (!videoSurface->attachToContext(context)) { - return nullptr; - } - if (!videoSurface->updateTexImage()) { - return nullptr; - } - return videoSurface->getTexture(); + std::lock_guard autoLock(locker); + if (!videoSurface->attachToContext(context)) { + return nullptr; + } + if (!videoSurface->updateTexImage()) { + return nullptr; + } + return videoSurface->getTexture(); } } // namespace pag diff --git a/src/platform/android/VideoImage.h b/src/platform/android/VideoImage.h index 022f59380f..665d310cb9 100644 --- a/src/platform/android/VideoImage.h +++ b/src/platform/android/VideoImage.h @@ -24,21 +24,21 @@ namespace pag { class VideoImage : public VideoBuffer { - public: - static std::shared_ptr MakeFrom(std::shared_ptr videoSurface, int width, - int height); +public: + static std::shared_ptr MakeFrom(std::shared_ptr videoSurface, int width, + int height); - size_t planeCount() const override { - return 1; - } + size_t planeCount() const override { + return 1; + } - protected: - std::shared_ptr makeTexture(Context* context) const override; +protected: + std::shared_ptr makeTexture(Context* context) const override; - private: - mutable std::mutex locker = {}; - std::shared_ptr videoSurface = nullptr; +private: + mutable std::mutex locker = {}; + std::shared_ptr videoSurface = nullptr; - VideoImage(std::shared_ptr videoSurface, int width, int height); + VideoImage(std::shared_ptr videoSurface, int width, int height); }; } // namespace pag diff --git a/src/platform/android/VideoSurface.cpp b/src/platform/android/VideoSurface.cpp index 100e36e5b1..267449b15f 100644 --- a/src/platform/android/VideoSurface.cpp +++ b/src/platform/android/VideoSurface.cpp @@ -31,165 +31,165 @@ static jmethodID VideoSurface_videoHeight; static jmethodID VideoSurface_onRelease; void VideoSurface::InitJNI(JNIEnv* env, const std::string& className) { - VideoSurfaceClass.reset(env, env->FindClass(className.c_str())); - std::string createSig = std::string("(II)L") + className + ";"; - VideoSurface_Make = env->GetStaticMethodID(VideoSurfaceClass.get(), "Make", createSig.c_str()); - VideoSurface_getOutputSurface = - env->GetMethodID(VideoSurfaceClass.get(), "getOutputSurface", "()Landroid/view/Surface;"); - VideoSurface_updateTexImage = env->GetMethodID(VideoSurfaceClass.get(), "updateTexImage", "()Z"); - VideoSurface_attachToGLContext = - env->GetMethodID(VideoSurfaceClass.get(), "attachToGLContext", "(I)Z"); - VideoSurface_videoWidth = env->GetMethodID(VideoSurfaceClass.get(), "videoWidth", "()I"); - VideoSurface_videoHeight = env->GetMethodID(VideoSurfaceClass.get(), "videoHeight", "()I"); - VideoSurface_onRelease = env->GetMethodID(VideoSurfaceClass.get(), "onRelease", "()V"); + VideoSurfaceClass.reset(env, env->FindClass(className.c_str())); + std::string createSig = std::string("(II)L") + className + ";"; + VideoSurface_Make = env->GetStaticMethodID(VideoSurfaceClass.get(), "Make", createSig.c_str()); + VideoSurface_getOutputSurface = + env->GetMethodID(VideoSurfaceClass.get(), "getOutputSurface", "()Landroid/view/Surface;"); + VideoSurface_updateTexImage = env->GetMethodID(VideoSurfaceClass.get(), "updateTexImage", "()Z"); + VideoSurface_attachToGLContext = + env->GetMethodID(VideoSurfaceClass.get(), "attachToGLContext", "(I)Z"); + VideoSurface_videoWidth = env->GetMethodID(VideoSurfaceClass.get(), "videoWidth", "()I"); + VideoSurface_videoHeight = env->GetMethodID(VideoSurfaceClass.get(), "videoHeight", "()I"); + VideoSurface_onRelease = env->GetMethodID(VideoSurfaceClass.get(), "onRelease", "()V"); } OESTexture::OESTexture(GLTextureInfo info, int width, int height, bool hasAlpha) : GLTexture(width, height, ImageOrigin::TopLeft), hasAlpha(hasAlpha) { - sampler.glInfo = info; - sampler.config = PixelConfig::RGBA_8888; + sampler.glInfo = info; + sampler.config = PixelConfig::RGBA_8888; } void OESTexture::setTextureSize(int width, int height) { - textureWidth = width; - textureHeight = height; - computeTransform(); + textureWidth = width; + textureHeight = height; + computeTransform(); } void OESTexture::computeTransform() { - if (textureWidth == 0 || textureHeight == 0 || hasAlpha) { - return; - } - // https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp;l=275;drc=master;bpv=0;bpt=1 - // https://stackoverflow.com/questions/6023400/opengl-es-texture-coordinates-slightly-off - - // In order to prevent bilinear sampling beyond the edge of the - // crop rectangle we may need to shrink it by 2 texels in each - // dimension. Normally this would just need to take 1/2 a texel - // off each end, but because the chroma channels of YUV420 images - // are subsampled we may need to shrink the crop region by a whole - // texel on each side. - auto shrinkAmount = 1.0f; - if (width() < textureWidth) { - tx = shrinkAmount / static_cast(textureWidth); - sx = (static_cast(width()) - (2.0f * shrinkAmount)) / static_cast(textureWidth); - } - if (height() < textureHeight) { - ty = shrinkAmount / static_cast(textureHeight); - sy = (static_cast(height()) - (2.0f * shrinkAmount)) / static_cast(textureHeight); - } + if (textureWidth == 0 || textureHeight == 0 || hasAlpha) { + return; + } + // https://cs.android.com/android/platform/superproject/+/master:frameworks/native/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp;l=275;drc=master;bpv=0;bpt=1 + // https://stackoverflow.com/questions/6023400/opengl-es-texture-coordinates-slightly-off + + // In order to prevent bilinear sampling beyond the edge of the + // crop rectangle we may need to shrink it by 2 texels in each + // dimension. Normally this would just need to take 1/2 a texel + // off each end, but because the chroma channels of YUV420 images + // are subsampled we may need to shrink the crop region by a whole + // texel on each side. + auto shrinkAmount = 1.0f; + if (width() < textureWidth) { + tx = shrinkAmount / static_cast(textureWidth); + sx = (static_cast(width()) - (2.0f * shrinkAmount)) / static_cast(textureWidth); + } + if (height() < textureHeight) { + ty = shrinkAmount / static_cast(textureHeight); + sy = (static_cast(height()) - (2.0f * shrinkAmount)) / static_cast(textureHeight); + } } Point OESTexture::getTextureCoord(float x, float y) const { - if (hasAlpha) { - // 如果有 alpha 通道,不需要缩小纹素 - return {x / static_cast(textureWidth), y / static_cast(textureHeight)}; - } - return {x / static_cast(width()) * sx + tx, y / static_cast(height()) * sy + ty}; + if (hasAlpha) { + // 如果有 alpha 通道,不需要缩小纹素 + return {x / static_cast(textureWidth), y / static_cast(textureHeight)}; + } + return {x / static_cast(width()) * sx + tx, y / static_cast(height()) * sy + ty}; } void OESTexture::onRelease(pag::Context* context) { - if (sampler.glInfo.id > 0) { - auto gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &sampler.glInfo.id); - } + if (sampler.glInfo.id > 0) { + auto gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &sampler.glInfo.id); + } } std::shared_ptr VideoSurface::Make(int width, int height, bool hasAlpha) { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return nullptr; - } - jobject surface = - env->CallStaticObjectMethod(VideoSurfaceClass.get(), VideoSurface_Make, width, height); - if (surface == nullptr) { - return nullptr; - } - auto videoSurface = std::shared_ptr( - new VideoSurface(env, surface, width, height, hasAlpha)); - env->DeleteLocalRef(surface); - return videoSurface; + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return nullptr; + } + jobject surface = + env->CallStaticObjectMethod(VideoSurfaceClass.get(), VideoSurface_Make, width, height); + if (surface == nullptr) { + return nullptr; + } + auto videoSurface = std::shared_ptr( + new VideoSurface(env, surface, width, height, hasAlpha)); + env->DeleteLocalRef(surface); + return videoSurface; } VideoSurface::VideoSurface(JNIEnv* env, jobject surface, int width, int height, bool hasAlpha) : width(width), height(height), hasAlpha(hasAlpha) { - videoSurface.reset(env, surface); + videoSurface.reset(env, surface); } VideoSurface::~VideoSurface() { - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return; - } - env->CallVoidMethod(videoSurface.get(), VideoSurface_onRelease); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return; + } + env->CallVoidMethod(videoSurface.get(), VideoSurface_onRelease); } jobject VideoSurface::getOutputSurface(JNIEnv* env) const { - return env->CallObjectMethod(videoSurface.get(), VideoSurface_getOutputSurface); + return env->CallObjectMethod(videoSurface.get(), VideoSurface_getOutputSurface); } bool VideoSurface::attachToContext(Context* context) { - if (oesTexture) { - if (deviceID != context->getDevice()->uniqueID()) { - LOGE("VideoSurface::attachToGLContext(): VideoSurface has already attached to a Context!"); - return false; + if (oesTexture) { + if (deviceID != context->getDevice()->uniqueID()) { + LOGE("VideoSurface::attachToGLContext(): VideoSurface has already attached to a Context!"); + return false; + } + return true; } + auto gl = GLContext::Unwrap(context); + GLTextureInfo glInfo = {}; + glInfo.target = GL::TEXTURE_EXTERNAL_OES; + glInfo.format = GL::RGBA8; + gl->genTextures(1, &glInfo.id); + oesTexture = Resource::Wrap(context, new OESTexture(glInfo, width, height, hasAlpha)); + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return false; + } + auto result = env->CallBooleanMethod(videoSurface.get(), VideoSurface_attachToGLContext, + oesTexture->getGLInfo().id); + deviceID = context->getDevice()->uniqueID(); + if (!result) { + LOGE("VideoSurface::attachToGLContext(): failed to attached to a Surface!"); + oesTexture = nullptr; + deviceID = 0; + return false; + } + oesTexture->attachedSurface.reset(env, videoSurface.get()); return true; - } - auto gl = GLContext::Unwrap(context); - GLTextureInfo glInfo = {}; - glInfo.target = GL::TEXTURE_EXTERNAL_OES; - glInfo.format = GL::RGBA8; - gl->genTextures(1, &glInfo.id); - oesTexture = Resource::Wrap(context, new OESTexture(glInfo, width, height, hasAlpha)); - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - auto result = env->CallBooleanMethod(videoSurface.get(), VideoSurface_attachToGLContext, - oesTexture->getGLInfo().id); - deviceID = context->getDevice()->uniqueID(); - if (!result) { - LOGE("VideoSurface::attachToGLContext(): failed to attached to a Surface!"); - oesTexture = nullptr; - deviceID = 0; - return false; - } - oesTexture->attachedSurface.reset(env, videoSurface.get()); - return true; } void VideoSurface::markHasNewTextureImage() { - hasPendingTextureImage = true; + hasPendingTextureImage = true; } bool VideoSurface::updateTexImage() { - if (!hasPendingTextureImage) { - return false; - } - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return false; - } - bool status = env->CallBooleanMethod(videoSurface.get(), VideoSurface_updateTexImage); - hasPendingTextureImage = false; - return status; + if (!hasPendingTextureImage) { + return false; + } + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return false; + } + bool status = env->CallBooleanMethod(videoSurface.get(), VideoSurface_updateTexImage); + hasPendingTextureImage = false; + return status; } std::shared_ptr VideoSurface::getTexture() { - if (oesTexture == nullptr) { - return nullptr; - } - if (oesTexture->textureWidth > 0) { + if (oesTexture == nullptr) { + return nullptr; + } + if (oesTexture->textureWidth > 0) { + return oesTexture; + } + auto env = JNIEnvironment::Current(); + if (env == nullptr) { + return nullptr; + } + auto textureWidth = env->CallIntMethod(videoSurface.get(), VideoSurface_videoWidth); + auto textureHeight = env->CallIntMethod(videoSurface.get(), VideoSurface_videoHeight); + oesTexture->setTextureSize(textureWidth, textureHeight); return oesTexture; - } - auto env = JNIEnvironment::Current(); - if (env == nullptr) { - return nullptr; - } - auto textureWidth = env->CallIntMethod(videoSurface.get(), VideoSurface_videoWidth); - auto textureHeight = env->CallIntMethod(videoSurface.get(), VideoSurface_videoHeight); - oesTexture->setTextureSize(textureWidth, textureHeight); - return oesTexture; } } // namespace pag diff --git a/src/platform/android/VideoSurface.h b/src/platform/android/VideoSurface.h index 80d960dd00..e2edbcf68d 100644 --- a/src/platform/android/VideoSurface.h +++ b/src/platform/android/VideoSurface.h @@ -23,63 +23,63 @@ namespace pag { class OESTexture : public GLTexture { - public: - OESTexture(GLTextureInfo info, int width, int height, bool hasAlpha); +public: + OESTexture(GLTextureInfo info, int width, int height, bool hasAlpha); - Point getTextureCoord(float x, float y) const override; + Point getTextureCoord(float x, float y) const override; - size_t memoryUsage() const override { - return 0; - } + size_t memoryUsage() const override { + return 0; + } - protected: - void onRelease(Context* context) override; +protected: + void onRelease(Context* context) override; - private: - void setTextureSize(int width, int height); +private: + void setTextureSize(int width, int height); - void computeTransform(); + void computeTransform(); - int textureWidth = 0; - int textureHeight = 0; - bool hasAlpha = false; - // 持有 Java 的 Surface,确保即使 GPUDecoder 提前释放也能正常被使用。 - Global attachedSurface; - float sx = 1.0f; - float sy = 1.0f; - float tx = 0.0f; - float ty = 0.0f; + int textureWidth = 0; + int textureHeight = 0; + bool hasAlpha = false; + // 持有 Java 的 Surface,确保即使 GPUDecoder 提前释放也能正常被使用。 + Global attachedSurface; + float sx = 1.0f; + float sy = 1.0f; + float tx = 0.0f; + float ty = 0.0f; - friend class VideoSurface; + friend class VideoSurface; }; class VideoSurface { - public: - static void InitJNI(JNIEnv* env, const std::string& className); +public: + static void InitJNI(JNIEnv* env, const std::string& className); - static std::shared_ptr Make(int width, int height, bool hasAlpha = false); + static std::shared_ptr Make(int width, int height, bool hasAlpha = false); - ~VideoSurface(); + ~VideoSurface(); - jobject getOutputSurface(JNIEnv* env) const; + jobject getOutputSurface(JNIEnv* env) const; - bool attachToContext(Context* context); + bool attachToContext(Context* context); - bool updateTexImage(); + bool updateTexImage(); - std::shared_ptr getTexture(); + std::shared_ptr getTexture(); - void markHasNewTextureImage(); + void markHasNewTextureImage(); - private: - Global videoSurface; - int width = 0; - int height = 0; - bool hasAlpha = false; - ID deviceID = 0; - std::shared_ptr oesTexture = nullptr; - mutable std::atomic_bool hasPendingTextureImage = {false}; +private: + Global videoSurface; + int width = 0; + int height = 0; + bool hasAlpha = false; + ID deviceID = 0; + std::shared_ptr oesTexture = nullptr; + mutable std::atomic_bool hasPendingTextureImage = {false}; - VideoSurface(JNIEnv* env, jobject surface, int width, int height, bool hasAlpha); + VideoSurface(JNIEnv* env, jobject surface, int width, int height, bool hasAlpha); }; } // namespace pag diff --git a/src/platform/cocoa/PAG.h b/src/platform/cocoa/PAG.h index f345420abf..725d3a50f8 100644 --- a/src/platform/cocoa/PAG.h +++ b/src/platform/cocoa/PAG.h @@ -20,9 +20,9 @@ __attribute__((visibility("default"))) @interface PAG : NSObject -/** - * Get SDK version information. - */ + /** + * Get SDK version information. + */ + (NSString*)SDKVersion; @end diff --git a/src/platform/cocoa/PAGComposition.h b/src/platform/cocoa/PAGComposition.h index 952275ff17..60985bf57a 100644 --- a/src/platform/cocoa/PAGComposition.h +++ b/src/platform/cocoa/PAGComposition.h @@ -22,9 +22,9 @@ __attribute__((visibility("default"))) @interface PAGComposition : PAGLayer -/** - * Make a empty PAGComposition with specified size. - */ + /** + * Make a empty PAGComposition with specified size. + */ + (PAGComposition*)Make:(CGSize)size; /** diff --git a/src/platform/cocoa/PAGFile.h b/src/platform/cocoa/PAGFile.h index 96cd707a73..6dc98bc5fd 100644 --- a/src/platform/cocoa/PAGFile.h +++ b/src/platform/cocoa/PAGFile.h @@ -25,9 +25,9 @@ __attribute__((visibility("default"))) @interface PAGFile : PAGComposition -/** - * The maximum tag level current SDK supports. - */ + /** + * The maximum tag level current SDK supports. + */ + (uint16_t)MaxSupportedTagLevel; /*** diff --git a/src/platform/cocoa/PAGFont.h b/src/platform/cocoa/PAGFont.h index 350c862cef..3fc805069b 100644 --- a/src/platform/cocoa/PAGFont.h +++ b/src/platform/cocoa/PAGFont.h @@ -21,9 +21,9 @@ __attribute__((visibility("default"))) @interface PAGFont : NSObject -/** - * A string with the name of the font family. - **/ + /** + * A string with the name of the font family. + **/ @property(nonatomic, copy) NSString* fontFamily; /** @@ -34,15 +34,15 @@ __attribute__((visibility("default"))) + (PAGFont*)RegisterFont:(NSString*)fontPath; + (PAGFont*)RegisterFont:(NSString*)fontPath - family:(NSString*)fontFamily - style:(NSString*)fontStyle; + family:(NSString*)fontFamily + style:(NSString*)fontStyle; + (PAGFont*)RegisterFont:(void*)data size:(size_t)length; + (PAGFont*)RegisterFont:(void*)data - size:(size_t)length - family:(NSString*)fontFamily - style:(NSString*)fontStyle; + size:(size_t)length + family:(NSString*)fontFamily + style:(NSString*)fontStyle; + (void)UnregisterFont:(PAGFont*)font; diff --git a/src/platform/cocoa/PAGImage.h b/src/platform/cocoa/PAGImage.h index c8d9490c30..cc8d922cf4 100644 --- a/src/platform/cocoa/PAGImage.h +++ b/src/platform/cocoa/PAGImage.h @@ -23,9 +23,9 @@ __attribute__((visibility("default"))) @interface PAGImage : NSObject -/** - * Creates a PAGImage object from a CGImage object, return null if it's not valid CGImage object. - */ + /** + * Creates a PAGImage object from a CGImage object, return null if it's not valid CGImage object. + */ + (PAGImage*)FromCGImage:(CGImageRef)cgImage; /** diff --git a/src/platform/cocoa/PAGImageLayer.h b/src/platform/cocoa/PAGImageLayer.h index 5ca16b1839..2bed51736c 100644 --- a/src/platform/cocoa/PAGImageLayer.h +++ b/src/platform/cocoa/PAGImageLayer.h @@ -24,9 +24,9 @@ @class PAGVideoRange; __attribute__((visibility("default"))) @interface PAGImageLayer : PAGLayer -/** - * Make a PAGImageLayer with size and duration(in microseconds). - */ + /** + * Make a PAGImageLayer with size and duration(in microseconds). + */ + (instancetype)Make:(CGSize)size duration:(int64_t)duration; /** diff --git a/src/platform/cocoa/PAGLayer.h b/src/platform/cocoa/PAGLayer.h index 5eaba9142e..d7fbd411a2 100644 --- a/src/platform/cocoa/PAGLayer.h +++ b/src/platform/cocoa/PAGLayer.h @@ -21,13 +21,13 @@ #import "PAGMarker.h" typedef NS_ENUM(NSInteger, PAGLayerType) { - PAGLayerTypeUnknown, - PAGLayerTypeNull, - PAGLayerTypeSolid, - PAGLayerTypeText, - PAGLayerTypeShape, - PAGLayerTypeImage, - PAGLayerTypePreCompose, + PAGLayerTypeUnknown, + PAGLayerTypeNull, + PAGLayerTypeSolid, + PAGLayerTypeText, + PAGLayerTypeShape, + PAGLayerTypeImage, + PAGLayerTypePreCompose, }; @class PAGComposition; @@ -36,9 +36,9 @@ typedef NS_ENUM(NSInteger, PAGLayerType) { __attribute__((visibility("default"))) @interface PAGLayer : NSObject -/** - * Returns the type of layer. - */ + /** + * Returns the type of layer. + */ - (PAGLayerType)layerType; /** diff --git a/src/platform/cocoa/PAGPlayer.h b/src/platform/cocoa/PAGPlayer.h index c41ea583e2..61520eefab 100644 --- a/src/platform/cocoa/PAGPlayer.h +++ b/src/platform/cocoa/PAGPlayer.h @@ -25,9 +25,9 @@ __attribute__((visibility("default"))) @interface PAGPlayer : NSObject -/** - * Returns the current PAGComposition for PAGPlayer to render as content. - */ + /** + * Returns the current PAGComposition for PAGPlayer to render as content. + */ - (PAGComposition*)getComposition; /** diff --git a/src/platform/cocoa/PAGScaleMode.h b/src/platform/cocoa/PAGScaleMode.h index ab404321a7..3fd93ae28d 100644 --- a/src/platform/cocoa/PAGScaleMode.h +++ b/src/platform/cocoa/PAGScaleMode.h @@ -17,15 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// typedef enum { - // The content is not scaled. - PAGScaleModeNone = 0, - // The content is stretched to fit. - PAGScaleModeStretch = 1, - // The content is scaled with respect to the original unscaled image's aspect ratio. This is the - // default value. - PAGScaleModeLetterBox = 2, - // The content is scaled to fit with respect to the original unscaled image's aspect ratio. This - // results in cropping - // on one axis. - PAGScaleModeZoom = 3, + // The content is not scaled. + PAGScaleModeNone = 0, + // The content is stretched to fit. + PAGScaleModeStretch = 1, + // The content is scaled with respect to the original unscaled image's aspect ratio. This is the + // default value. + PAGScaleModeLetterBox = 2, + // The content is scaled to fit with respect to the original unscaled image's aspect ratio. This + // results in cropping + // on one axis. + PAGScaleModeZoom = 3, } PAGScaleMode; diff --git a/src/platform/cocoa/PAGSolidLayer.h b/src/platform/cocoa/PAGSolidLayer.h index 9d7d9ba896..4b52455f11 100644 --- a/src/platform/cocoa/PAGSolidLayer.h +++ b/src/platform/cocoa/PAGSolidLayer.h @@ -23,9 +23,9 @@ __attribute__((visibility("default"))) @interface PAGSolidLayer : PAGLayer -/** - * Returns the layer's solid color. - */ + /** + * Returns the layer's solid color. + */ - (CocoaColor*)solidColor; /** diff --git a/src/platform/cocoa/PAGText.h b/src/platform/cocoa/PAGText.h index dddefba2b4..7f6610ee4a 100644 --- a/src/platform/cocoa/PAGText.h +++ b/src/platform/cocoa/PAGText.h @@ -20,13 +20,13 @@ #include "CocoaUtils.h" enum { - PAGJustificationLeftJustify = 0, - PAGJustificationCenterJustify = 1, - PAGJustificationRightJustify = 2, - PAGJustificationFullJustifyLastLineLeft = 3, - PAGJustificationFullJustifyLastLineRight = 4, - PAGJustificationFullJustifyLastLineCenter = 5, - PAGJustificationFullJustifyLastLineFull = 6 + PAGJustificationLeftJustify = 0, + PAGJustificationCenterJustify = 1, + PAGJustificationRightJustify = 2, + PAGJustificationFullJustifyLastLineLeft = 3, + PAGJustificationFullJustifyLastLineRight = 4, + PAGJustificationFullJustifyLastLineCenter = 5, + PAGJustificationFullJustifyLastLineFull = 6 }; /** @@ -35,9 +35,9 @@ enum { __attribute__((visibility("default"))) @interface PAGText : NSObject -/** - * When true, the text layer shows a fill. - */ + /** + * When true, the text layer shows a fill. + */ @property(nonatomic, assign) bool applyFill; /** diff --git a/src/platform/cocoa/PAGTextLayer.h b/src/platform/cocoa/PAGTextLayer.h index c5f080658f..f964d004a8 100644 --- a/src/platform/cocoa/PAGTextLayer.h +++ b/src/platform/cocoa/PAGTextLayer.h @@ -25,9 +25,9 @@ __attribute__((visibility("default"))) @interface PAGTextLayer : PAGLayer -/** - * Returns the TextLayer’s fill color. - */ + /** + * Returns the TextLayer’s fill color. + */ - (CocoaColor*)fillColor; /** diff --git a/src/platform/cocoa/PAGTimeStretchMode.h b/src/platform/cocoa/PAGTimeStretchMode.h index b779cd9f2a..ef0008523f 100644 --- a/src/platform/cocoa/PAGTimeStretchMode.h +++ b/src/platform/cocoa/PAGTimeStretchMode.h @@ -17,17 +17,17 @@ ///////////////////////////////////////////////////////////////////////////////////////////////// typedef enum { - // Keep the original playing speed, and display the last frame if the content's duration is less - // than target duration. - PAGTimeStretchModeNone = 0, - // Change the playing speed of the content to fit target duration. - PAGTimeStretchModeScale = 1, - // Keep the original playing speed, but repeat the content if the content's duration is less than - // target duration. - // This is the default mode. - PAGTimeStretchModeRepeat = 2, - // Keep the original playing speed, but repeat the content in reversed if the content's duration - // is less than - // target duration. - PAGTimeStretchModeRepeatInverted = 3, + // Keep the original playing speed, and display the last frame if the content's duration is less + // than target duration. + PAGTimeStretchModeNone = 0, + // Change the playing speed of the content to fit target duration. + PAGTimeStretchModeScale = 1, + // Keep the original playing speed, but repeat the content if the content's duration is less than + // target duration. + // This is the default mode. + PAGTimeStretchModeRepeat = 2, + // Keep the original playing speed, but repeat the content in reversed if the content's duration + // is less than + // target duration. + PAGTimeStretchModeRepeatInverted = 3, } PAGTimeStretchMode; diff --git a/src/platform/cocoa/PAGVideoDecoder.h b/src/platform/cocoa/PAGVideoDecoder.h index 3089eacd24..3362bd190d 100644 --- a/src/platform/cocoa/PAGVideoDecoder.h +++ b/src/platform/cocoa/PAGVideoDecoder.h @@ -21,9 +21,9 @@ __attribute__((visibility("default"))) @interface PAGVideoDecoder : NSObject -/** - * Register a software decoder factory to implement the decoder fallback mechanism. - */ + /** + * Register a software decoder factory to implement the decoder fallback mechanism. + */ + (void)RegisterSoftwareDecoderFactory:(void*)decoderFactory; /** diff --git a/src/platform/cocoa/PAGVideoRange.h b/src/platform/cocoa/PAGVideoRange.h index 718adea39f..3f77c49f0a 100644 --- a/src/platform/cocoa/PAGVideoRange.h +++ b/src/platform/cocoa/PAGVideoRange.h @@ -23,9 +23,9 @@ */ __attribute__((visibility("default"))) @interface PAGVideoRange : NSObject -/** - * The start time of the source video, in microseconds. - */ + /** + * The start time of the source video, in microseconds. + */ @property(nonatomic) int64_t startTime; /** * The end time of the source video (not included), in microseconds. diff --git a/src/platform/cocoa/private/CocoaPlatform.h b/src/platform/cocoa/private/CocoaPlatform.h index 29f65a802d..5e94a81139 100644 --- a/src/platform/cocoa/private/CocoaPlatform.h +++ b/src/platform/cocoa/private/CocoaPlatform.h @@ -22,28 +22,28 @@ namespace pag { class CocoaPlatform : public Platform { - public: - bool hasHardwareDecoder() const override { - return true; - } +public: + bool hasHardwareDecoder() const override { + return true; + } - std::shared_ptr makeHardwareBuffer(int width, int height, - bool alphaOnly) const override; + std::shared_ptr makeHardwareBuffer(int width, int height, + bool alphaOnly) const override; - std::shared_ptr makeImage(const std::string& filePath) const override; + std::shared_ptr makeImage(const std::string& filePath) const override; - std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; + std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; - PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; + PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; - PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; + PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; - bool registerFallbackFonts() const override; + bool registerFallbackFonts() const override; - NALUType naluType() const override { - return NALUType::AVCC; - } + NALUType naluType() const override { + return NALUType::AVCC; + } - void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; + void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; }; } // namespace pag diff --git a/src/platform/cocoa/private/ColorUtility.h b/src/platform/cocoa/private/ColorUtility.h index 382429448d..62669fbed3 100644 --- a/src/platform/cocoa/private/ColorUtility.h +++ b/src/platform/cocoa/private/ColorUtility.h @@ -20,8 +20,8 @@ #include "platform/cocoa/CocoaUtils.h" class ColorUtility { - public: - static CocoaColor* ToCocoaColor(pag::Color color); +public: + static CocoaColor* ToCocoaColor(pag::Color color); - static pag::Color ToColor(CocoaColor* color); + static pag::Color ToColor(CocoaColor* color); }; diff --git a/src/platform/cocoa/private/FontConfig.h b/src/platform/cocoa/private/FontConfig.h index 048daf16c1..c81e1c51ee 100644 --- a/src/platform/cocoa/private/FontConfig.h +++ b/src/platform/cocoa/private/FontConfig.h @@ -22,11 +22,11 @@ namespace pag { class FontConfig { - public: - static bool RegisterFallbackFonts(); +public: + static bool RegisterFallbackFonts(); - static PAGFont Parse(const void* data, size_t length, int); + static PAGFont Parse(const void* data, size_t length, int); - static PAGFont Parse(const std::string& fontPath, int); + static PAGFont Parse(const std::string& fontPath, int); }; } // namespace pag \ No newline at end of file diff --git a/src/platform/cocoa/private/ImageUtilsCocoa.h b/src/platform/cocoa/private/ImageUtilsCocoa.h index 7e585706d9..30f5a697f5 100644 --- a/src/platform/cocoa/private/ImageUtilsCocoa.h +++ b/src/platform/cocoa/private/ImageUtilsCocoa.h @@ -27,5 +27,5 @@ bool ReadPixelsFromCGImage(CGImageRef cgImage, const ImageInfo& dstInfo, void* r CGImagePropertyOrientation orientation = kCGImagePropertyOrientationUp); CGAffineTransform EncodedOriginToCGAffineTransform(CGImagePropertyOrientation orientation, - int* width, int* height); + int* width, int* height); } // namespace pag diff --git a/src/platform/cocoa/private/NativeHardwareBuffer.h b/src/platform/cocoa/private/NativeHardwareBuffer.h index 1bba813e5e..cc54c22d45 100644 --- a/src/platform/cocoa/private/NativeHardwareBuffer.h +++ b/src/platform/cocoa/private/NativeHardwareBuffer.h @@ -23,26 +23,26 @@ namespace pag { class NativeHardwareBuffer : public PixelBuffer { - public: - static std::shared_ptr MakeAdopted(CVPixelBufferRef pixelBuffer); +public: + static std::shared_ptr MakeAdopted(CVPixelBufferRef pixelBuffer); - ~NativeHardwareBuffer() override; + ~NativeHardwareBuffer() override; - void* lockPixels() override; + void* lockPixels() override; - void unlockPixels() override; + void unlockPixels() override; - std::shared_ptr makeTexture(Context* context) const override { - return GLHardwareTexture::MakeFrom(context, pixelBuffer, adopted); - } + std::shared_ptr makeTexture(Context* context) const override { + return GLHardwareTexture::MakeFrom(context, pixelBuffer, adopted); + } - private: - CVPixelBufferRef pixelBuffer = nullptr; - bool adopted = false; +private: + CVPixelBufferRef pixelBuffer = nullptr; + bool adopted = false; - NativeHardwareBuffer(CVPixelBufferRef pixelBuffer, bool adopted); + NativeHardwareBuffer(CVPixelBufferRef pixelBuffer, bool adopted); - friend class CocoaPlatform; + friend class CocoaPlatform; }; } // namespace pag diff --git a/src/platform/cocoa/private/NativeImage.h b/src/platform/cocoa/private/NativeImage.h index 19145aee55..8f23fe8111 100644 --- a/src/platform/cocoa/private/NativeImage.h +++ b/src/platform/cocoa/private/NativeImage.h @@ -23,18 +23,18 @@ namespace pag { class NativeImage : public Image { - public: - static std::unique_ptr MakeFrom(const std::string& filePath); +public: + static std::unique_ptr MakeFrom(const std::string& filePath); - static std::unique_ptr MakeFrom(std::shared_ptr imageBytes); + static std::unique_ptr MakeFrom(std::shared_ptr imageBytes); - bool readPixels(const ImageInfo& dstInfo, void* dstPixels) const override; + bool readPixels(const ImageInfo& dstInfo, void* dstPixels) const override; - private: - std::string imagePath; - std::shared_ptr imageBytes; +private: + std::string imagePath; + std::shared_ptr imageBytes; - NativeImage(int width, int height) : Image(width, height, Orientation::TopLeft) { - } + NativeImage(int width, int height) : Image(width, height, Orientation::TopLeft) { + } }; } // namespace pag diff --git a/src/platform/cocoa/private/PAGFontImpl.h b/src/platform/cocoa/private/PAGFontImpl.h index 3f50b3f338..63acd7cfb2 100644 --- a/src/platform/cocoa/private/PAGFontImpl.h +++ b/src/platform/cocoa/private/PAGFontImpl.h @@ -23,14 +23,14 @@ @interface PAGFontImpl : NSObject + (PAGFont*)RegisterFont:(NSString*)fontPath - family:(NSString*)fontFamily - style:(NSString*)fontStyle; + family:(NSString*)fontFamily + style:(NSString*)fontStyle; ; + (PAGFont*)RegisterFont:(void*)data - size:(size_t)length - family:(NSString*)fontFamily - style:(NSString*)fontStyle; + size:(size_t)length + family:(NSString*)fontFamily + style:(NSString*)fontStyle; + (void)UnregisterFont:(PAGFont*)font; diff --git a/src/platform/cocoa/private/PAGLayer+Internal.h b/src/platform/cocoa/private/PAGLayer+Internal.h index 5a3ee83d50..2a7f086d51 100644 --- a/src/platform/cocoa/private/PAGLayer+Internal.h +++ b/src/platform/cocoa/private/PAGLayer+Internal.h @@ -20,7 +20,7 @@ #import "platform/cocoa/PAGLayer.h" @interface PAGLayer () { - id _impl; + id _impl; } - (instancetype)initWithImpl:(id)impl; diff --git a/src/platform/cocoa/private/PixelBufferUtils.h b/src/platform/cocoa/private/PixelBufferUtils.h index 2adfdf30d6..771a5cddce 100644 --- a/src/platform/cocoa/private/PixelBufferUtils.h +++ b/src/platform/cocoa/private/PixelBufferUtils.h @@ -22,7 +22,7 @@ namespace pag { class PixelBufferUtils { - public: - static CVPixelBufferRef Make(int width, int height, bool alphaOnly = false); +public: + static CVPixelBufferRef Make(int width, int height, bool alphaOnly = false); }; } // namespace pag \ No newline at end of file diff --git a/src/platform/ios/PAGSurface.h b/src/platform/ios/PAGSurface.h index 1e6c6674a8..6af1858662 100644 --- a/src/platform/ios/PAGSurface.h +++ b/src/platform/ios/PAGSurface.h @@ -25,10 +25,10 @@ __attribute__((visibility("default"))) @interface PAGSurface : NSObject -/** - * Creates a new PAGSurface from specified CAEAGLLayer. The GPU context will be created internally - * by PAGSurface. - */ + /** + * Creates a new PAGSurface from specified CAEAGLLayer. The GPU context will be created internally + * by PAGSurface. + */ + (PAGSurface*)FromLayer:(CAEAGLLayer*)layer; /** diff --git a/src/platform/ios/PAGView.h b/src/platform/ios/PAGView.h index 62578995c4..48e1c36985 100755 --- a/src/platform/ios/PAGView.h +++ b/src/platform/ios/PAGView.h @@ -69,9 +69,9 @@ __attribute__((visibility("default"))) @interface PAGView : UIView -/** - * Default is NO. - */ + /** + * Default is NO. + */ @property(nonatomic) BOOL sync; /** diff --git a/src/platform/ios/private/GLNV12Texture.h b/src/platform/ios/private/GLNV12Texture.h index 8183426898..468015a9d5 100644 --- a/src/platform/ios/private/GLNV12Texture.h +++ b/src/platform/ios/private/GLNV12Texture.h @@ -23,27 +23,27 @@ namespace pag { class GLNV12Texture : public GLYUVTexture { - public: - static std::shared_ptr MakeFrom(Context* context, CVPixelBufferRef pixelBuffer, - YUVColorSpace colorSpace, YUVColorRange colorRange); +public: + static std::shared_ptr MakeFrom(Context* context, CVPixelBufferRef pixelBuffer, + YUVColorSpace colorSpace, YUVColorRange colorRange); - GLNV12Texture(CVPixelBufferRef pixelBuffer, - YUVColorSpace colorSpace, YUVColorRange colorRange); + GLNV12Texture(CVPixelBufferRef pixelBuffer, + YUVColorSpace colorSpace, YUVColorRange colorRange); - ~GLNV12Texture() override; + ~GLNV12Texture() override; - YUVPixelFormat pixelFormat() const override { - return YUVPixelFormat::NV12; - } + YUVPixelFormat pixelFormat() const override { + return YUVPixelFormat::NV12; + } - size_t memoryUsage() const override; + size_t memoryUsage() const override; - protected: - void onRelease(Context* context) override; +protected: + void onRelease(Context* context) override; - private: - CVPixelBufferRef pixelBuffer = nullptr; - CVOpenGLESTextureRef lumaTexture = nullptr; - CVOpenGLESTextureRef chromaTexture = nullptr; +private: + CVPixelBufferRef pixelBuffer = nullptr; + CVOpenGLESTextureRef lumaTexture = nullptr; + CVOpenGLESTextureRef chromaTexture = nullptr; }; } // namespace pag diff --git a/src/platform/ios/private/GPUDecoder.h b/src/platform/ios/private/GPUDecoder.h index ce43712c4f..2d99bd3e9d 100644 --- a/src/platform/ios/private/GPUDecoder.h +++ b/src/platform/ios/private/GPUDecoder.h @@ -26,50 +26,50 @@ namespace pag { class GPUDecoder : public VideoDecoder { - public: - explicit GPUDecoder(const VideoConfig& config); +public: + explicit GPUDecoder(const VideoConfig& config); - ~GPUDecoder() override; + ~GPUDecoder() override; - bool isInitialized = false; + bool isInitialized = false; - pag::DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; + pag::DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; - pag::DecodingResult onEndOfStream() override; + pag::DecodingResult onEndOfStream() override; - pag::DecodingResult onDecodeFrame() override; + pag::DecodingResult onDecodeFrame() override; - void onFlush() override; + void onFlush() override; - int64_t presentationTime() override; + int64_t presentationTime() override; - std::shared_ptr onRenderFrame() override; + std::shared_ptr onRenderFrame() override; - private: - VTDecompressionSessionRef session = nullptr; - CMFormatDescriptionRef videoFormatDescription = nullptr; - YUVColorSpace sourceColorSpace = YUVColorSpace::Rec601; - YUVColorSpace destinationColorSpace = YUVColorSpace::Rec601; - YUVColorRange colorRange = YUVColorRange::MPEG; +private: + VTDecompressionSessionRef session = nullptr; + CMFormatDescriptionRef videoFormatDescription = nullptr; + YUVColorSpace sourceColorSpace = YUVColorSpace::Rec601; + YUVColorSpace destinationColorSpace = YUVColorSpace::Rec601; + YUVColorRange colorRange = YUVColorRange::MPEG; - bool initVideoToolBox(const std::vector>& headers, - const std::string& mimeType); - bool resetVideoToolBox(); - void cleanResources(); + bool initVideoToolBox(const std::vector>& headers, + const std::string& mimeType); + bool resetVideoToolBox(); + void cleanResources(); - struct OutputFrame { - int64_t frameTime = 0; - CVPixelBufferRef outputPixelBuffer = nullptr; - }; + struct OutputFrame { + int64_t frameTime = 0; + CVPixelBufferRef outputPixelBuffer = nullptr; + }; - int64_t sendFrameTime = -1; - std::list pendingFrames{}; - std::unordered_map outputFrameCaches{}; - int maxNumReorder = 0; - bool inputEndOfStream = false; + int64_t sendFrameTime = -1; + std::list pendingFrames{}; + std::unordered_map outputFrameCaches{}; + int maxNumReorder = 0; + bool inputEndOfStream = false; - CMBlockBufferRef blockBuffer = nullptr; - CMSampleBufferRef sampleBuffer = nullptr; - OutputFrame* outputFrame = nullptr; + CMBlockBufferRef blockBuffer = nullptr; + CMSampleBufferRef sampleBuffer = nullptr; + OutputFrame* outputFrame = nullptr; }; } // namespace pag diff --git a/src/platform/ios/private/GPUDrawable.h b/src/platform/ios/private/GPUDrawable.h index 6e5f8c0a8d..a3b6fd44fb 100644 --- a/src/platform/ios/private/GPUDrawable.h +++ b/src/platform/ios/private/GPUDrawable.h @@ -27,42 +27,42 @@ extern NSString* const kGPURenderTargetBufferPreparedNotification; extern NSString* const kPreparedAsync; class GPUDrawable : public Drawable { - public: - static std::shared_ptr FromLayer(CAEAGLLayer* layer); +public: + static std::shared_ptr FromLayer(CAEAGLLayer* layer); - static std::shared_ptr FromCVPixelBuffer(CVPixelBufferRef pixelBuffer, - EAGLContext* eaglContext = nil); + static std::shared_ptr FromCVPixelBuffer(CVPixelBufferRef pixelBuffer, + EAGLContext* eaglContext = nil); - ~GPUDrawable() override; + ~GPUDrawable() override; - int width() const override; + int width() const override; - int height() const override; + int height() const override; - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context* context) override; + void present(Context* context) override; - CVPixelBufferRef getCVPixelBuffer(); + CVPixelBufferRef getCVPixelBuffer(); - private: - std::weak_ptr weakThis; - int _width = 0; - int _height = 0; - CAEAGLLayer* layer = nil; - CVPixelBufferRef pixelBuffer = nil; - EAGLContext* eaglContext = nil; - std::shared_ptr window = nullptr; - std::shared_ptr surface = nullptr; - std::atomic bufferPreparing; +private: + std::weak_ptr weakThis; + int _width = 0; + int _height = 0; + CAEAGLLayer* layer = nil; + CVPixelBufferRef pixelBuffer = nil; + EAGLContext* eaglContext = nil; + std::shared_ptr window = nullptr; + std::shared_ptr surface = nullptr; + std::atomic bufferPreparing; - static bool IsInMainThread(); + static bool IsInMainThread(); - explicit GPUDrawable(CAEAGLLayer* layer); - explicit GPUDrawable(CVPixelBufferRef pixelBuffer); + explicit GPUDrawable(CAEAGLLayer* layer); + explicit GPUDrawable(CVPixelBufferRef pixelBuffer); }; } // namespace pag diff --git a/src/platform/ios/private/NativePlatform.h b/src/platform/ios/private/NativePlatform.h index d5e1574b73..fb6fef4967 100644 --- a/src/platform/ios/private/NativePlatform.h +++ b/src/platform/ios/private/NativePlatform.h @@ -22,10 +22,10 @@ namespace pag { class NativePlatform : public CocoaPlatform { - public: - std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; +public: + std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; - void reportStatisticalData( - std::unordered_map& reportMap) const override; + void reportStatisticalData( + std::unordered_map& reportMap) const override; }; } // namespace pag diff --git a/src/platform/ios/private/PAGSurfaceImpl.h b/src/platform/ios/private/PAGSurfaceImpl.h index 9c5b54e3e1..89b672c369 100644 --- a/src/platform/ios/private/PAGSurfaceImpl.h +++ b/src/platform/ios/private/PAGSurfaceImpl.h @@ -31,7 +31,7 @@ + (PAGSurfaceImpl*)FromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer; + (PAGSurfaceImpl*)FromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer - context:(EAGLContext*)eaglContext; + context:(EAGLContext*)eaglContext; + (PAGSurfaceImpl*)MakeFromGPU:(CGSize)size; diff --git a/src/platform/ios/private/ValueAnimator.h b/src/platform/ios/private/ValueAnimator.h index 0f775a1896..9e575a9e50 100644 --- a/src/platform/ios/private/ValueAnimator.h +++ b/src/platform/ios/private/ValueAnimator.h @@ -33,13 +33,13 @@ @end @interface ValueAnimator : NSObject { - int64_t duration; - int64_t startTime; - int64_t playTime; - int repeatCount; - int repeatedTimes; - NSUInteger animatorId; - id animatorListener; + int64_t duration; + int64_t startTime; + int64_t playTime; + int repeatCount; + int repeatedTimes; + NSUInteger animatorId; + id animatorListener; } - (void)setListener:(id)listener; diff --git a/src/platform/ios/private/VideoImage.h b/src/platform/ios/private/VideoImage.h index 05b16067fd..2d63bec0b0 100644 --- a/src/platform/ios/private/VideoImage.h +++ b/src/platform/ios/private/VideoImage.h @@ -23,25 +23,25 @@ namespace pag { class VideoImage : public VideoBuffer { - public: - static std::shared_ptr MakeFrom(CVPixelBufferRef pixelBuffer, - YUVColorSpace colorSpace, - YUVColorRange colorRange); +public: + static std::shared_ptr MakeFrom(CVPixelBufferRef pixelBuffer, + YUVColorSpace colorSpace, + YUVColorRange colorRange); - ~VideoImage() override; + ~VideoImage() override; - size_t planeCount() const override; + size_t planeCount() const override; - protected: - std::shared_ptr makeTexture(Context* context) const override { - return GLNV12Texture::MakeFrom(context, pixelBuffer, _colorSpace, _colorRange); - } +protected: + std::shared_ptr makeTexture(Context* context) const override { + return GLNV12Texture::MakeFrom(context, pixelBuffer, _colorSpace, _colorRange); + } - private: - CVPixelBufferRef pixelBuffer = nullptr; - YUVColorSpace _colorSpace = YUVColorSpace::Rec601; - YUVColorRange _colorRange = YUVColorRange::MPEG; +private: + CVPixelBufferRef pixelBuffer = nullptr; + YUVColorSpace _colorSpace = YUVColorSpace::Rec601; + YUVColorRange _colorRange = YUVColorRange::MPEG; - VideoImage(CVPixelBufferRef pixelBuffer, YUVColorSpace colorSpace, YUVColorRange colorRange); + VideoImage(CVPixelBufferRef pixelBuffer, YUVColorSpace colorSpace, YUVColorRange colorRange); }; } // namespace pag diff --git a/src/platform/mac/PAGView.h b/src/platform/mac/PAGView.h index c15a5ee534..f8dd168faf 100755 --- a/src/platform/mac/PAGView.h +++ b/src/platform/mac/PAGView.h @@ -69,10 +69,10 @@ __attribute__((visibility("default"))) @interface PAGView : NSView -/** - * Adds a listener to the set of listeners that are sent events through the life of an animation, - * such as start, repeat, and end. - */ + /** + * Adds a listener to the set of listeners that are sent events through the life of an animation, + * such as start, repeat, and end. + */ - (void)addListener:(id)listener; /** diff --git a/src/platform/mac/private/GPUDecoder.h b/src/platform/mac/private/GPUDecoder.h index 96ab7150cc..b791e774b4 100644 --- a/src/platform/mac/private/GPUDecoder.h +++ b/src/platform/mac/private/GPUDecoder.h @@ -26,48 +26,48 @@ namespace pag { class GPUDecoder : public VideoDecoder { - public: - explicit GPUDecoder(const VideoConfig& config); +public: + explicit GPUDecoder(const VideoConfig& config); - ~GPUDecoder() override; + ~GPUDecoder() override; - bool isInitialized = false; + bool isInitialized = false; - pag::DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; + pag::DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; - pag::DecodingResult onEndOfStream() override; + pag::DecodingResult onEndOfStream() override; - pag::DecodingResult onDecodeFrame() override; + pag::DecodingResult onDecodeFrame() override; - void onFlush() override; + void onFlush() override; - int64_t presentationTime() override; + int64_t presentationTime() override; - std::shared_ptr onRenderFrame() override; + std::shared_ptr onRenderFrame() override; - private: - VTDecompressionSessionRef session = nullptr; - CMFormatDescriptionRef videoFormatDescription = nullptr; - YUVColorSpace colorSpace = YUVColorSpace::Rec601; +private: + VTDecompressionSessionRef session = nullptr; + CMFormatDescriptionRef videoFormatDescription = nullptr; + YUVColorSpace colorSpace = YUVColorSpace::Rec601; - bool initVideoToolBox(const std::vector>& headers, - const std::string& mimeType); - bool resetVideoToolBox(); - void cleanResources(); + bool initVideoToolBox(const std::vector>& headers, + const std::string& mimeType); + bool resetVideoToolBox(); + void cleanResources(); - struct OutputFrame { - int64_t frameTime = 0; - CVPixelBufferRef outputPixelBuffer = nullptr; - }; + struct OutputFrame { + int64_t frameTime = 0; + CVPixelBufferRef outputPixelBuffer = nullptr; + }; - int64_t sendFrameTime = -1; - std::list pendingFrames{}; - std::unordered_map outputFrameCaches{}; - size_t maxNumReorder = 0; - bool inputEndOfStream = false; + int64_t sendFrameTime = -1; + std::list pendingFrames{}; + std::unordered_map outputFrameCaches{}; + size_t maxNumReorder = 0; + bool inputEndOfStream = false; - CMBlockBufferRef blockBuffer = nullptr; - CMSampleBufferRef sampleBuffer = nullptr; - OutputFrame* outputFrame = nullptr; + CMBlockBufferRef blockBuffer = nullptr; + CMSampleBufferRef sampleBuffer = nullptr; + OutputFrame* outputFrame = nullptr; }; } // namespace pag diff --git a/src/platform/mac/private/GPUDrawable.h b/src/platform/mac/private/GPUDrawable.h index 92241f4659..421242b3af 100644 --- a/src/platform/mac/private/GPUDrawable.h +++ b/src/platform/mac/private/GPUDrawable.h @@ -23,37 +23,37 @@ namespace pag { class GPUDrawable : public Drawable { - public: - static std::shared_ptr FromView(NSView* view); +public: + static std::shared_ptr FromView(NSView* view); - static std::shared_ptr FromCVPixelBuffer(CVPixelBufferRef pixelBuffer); + static std::shared_ptr FromCVPixelBuffer(CVPixelBufferRef pixelBuffer); - ~GPUDrawable() override; + ~GPUDrawable() override; - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context* context) override; + void present(Context* context) override; - private: - int _width = 0; - int _height = 0; - NSView* view = nil; - CVPixelBufferRef pixelBuffer = nil; - std::shared_ptr window = nullptr; +private: + int _width = 0; + int _height = 0; + NSView* view = nil; + CVPixelBufferRef pixelBuffer = nil; + std::shared_ptr window = nullptr; - explicit GPUDrawable(NSView* view); - explicit GPUDrawable(CVPixelBufferRef pixelBuffer); + explicit GPUDrawable(NSView* view); + explicit GPUDrawable(CVPixelBufferRef pixelBuffer); }; } // namespace pag diff --git a/src/platform/mac/private/NativePlatform.h b/src/platform/mac/private/NativePlatform.h index 7f6be6ab6b..8924ea3dd0 100644 --- a/src/platform/mac/private/NativePlatform.h +++ b/src/platform/mac/private/NativePlatform.h @@ -22,11 +22,11 @@ namespace pag { class NativePlatform : public CocoaPlatform { - public: - NALUType naluType() const override; +public: + NALUType naluType() const override; - void setNALUType(NALUType type) const; + void setNALUType(NALUType type) const; - std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; + std::unique_ptr makeHardwareDecoder(const VideoConfig& config) const override; }; } // namespace pag diff --git a/src/platform/mac/private/ValueAnimator.h b/src/platform/mac/private/ValueAnimator.h index 1920844dda..b6c9542d56 100644 --- a/src/platform/mac/private/ValueAnimator.h +++ b/src/platform/mac/private/ValueAnimator.h @@ -35,13 +35,13 @@ @end @interface ValueAnimator : NSObject { - int64_t duration; - int64_t startTime; - int64_t playTime; - int repeatCount; - int lastRepeatCount; - int64_t animatorId; - id animatorListener; + int64_t duration; + int64_t startTime; + int64_t playTime; + int repeatCount; + int lastRepeatCount; + int64_t animatorId; + id animatorListener; } - (void)setListener:(id)listener; diff --git a/src/platform/mac/private/VideoImage.h b/src/platform/mac/private/VideoImage.h index bb6867be4b..532483b6e1 100644 --- a/src/platform/mac/private/VideoImage.h +++ b/src/platform/mac/private/VideoImage.h @@ -23,21 +23,21 @@ namespace pag { class VideoImage : public VideoBuffer { - public: - static std::shared_ptr MakeFrom(CVPixelBufferRef pixelBuffer); +public: + static std::shared_ptr MakeFrom(CVPixelBufferRef pixelBuffer); - ~VideoImage() override; + ~VideoImage() override; - size_t planeCount() const override; + size_t planeCount() const override; - protected: - std::shared_ptr makeTexture(Context* context) const override { - return GLHardwareTexture::MakeFrom(context, pixelBuffer, false); - } +protected: + std::shared_ptr makeTexture(Context* context) const override { + return GLHardwareTexture::MakeFrom(context, pixelBuffer, false); + } - private: - CVPixelBufferRef pixelBuffer = nullptr; +private: + CVPixelBufferRef pixelBuffer = nullptr; - explicit VideoImage(CVPixelBufferRef pixelBuffer); + explicit VideoImage(CVPixelBufferRef pixelBuffer); }; } // namespace pag diff --git a/src/platform/qt/GPUDrawable.cpp b/src/platform/qt/GPUDrawable.cpp index 82c45c1aca..1d85fc071b 100644 --- a/src/platform/qt/GPUDrawable.cpp +++ b/src/platform/qt/GPUDrawable.cpp @@ -23,46 +23,46 @@ namespace pag { std::shared_ptr GPUDrawable::MakeFrom(QQuickItem* quickItem, - QOpenGLContext* sharedContext) { - auto window = QGLWindow::MakeFrom(quickItem, sharedContext); - if (window == nullptr) { - return nullptr; - } - return std::shared_ptr(new GPUDrawable(quickItem, std::move(window))); + QOpenGLContext* sharedContext) { + auto window = QGLWindow::MakeFrom(quickItem, sharedContext); + if (window == nullptr) { + return nullptr; + } + return std::shared_ptr(new GPUDrawable(quickItem, std::move(window))); } GPUDrawable::GPUDrawable(QQuickItem* quickItem, std::shared_ptr window) : quickItem(quickItem), window(std::move(window)) { - GPUDrawable::updateSize(); + GPUDrawable::updateSize(); } void GPUDrawable::updateSize() { - auto nativeWindow = quickItem->window(); - auto pixelRatio = nativeWindow ? nativeWindow->devicePixelRatio() : 1.0f; - _width = static_cast(ceil(quickItem->width() * pixelRatio)); - _height = static_cast(ceil(quickItem->height() * pixelRatio)); + auto nativeWindow = quickItem->window(); + auto pixelRatio = nativeWindow ? nativeWindow->devicePixelRatio() : 1.0f; + _width = static_cast(ceil(quickItem->width() * pixelRatio)); + _height = static_cast(ceil(quickItem->height() * pixelRatio)); } std::shared_ptr GPUDrawable::getDevice() { - if (_width <= 0 || _height <= 0) { - return nullptr; - } - return window->getDevice(); + if (_width <= 0 || _height <= 0) { + return nullptr; + } + return window->getDevice(); } std::shared_ptr GPUDrawable::createSurface(Context* context) { - return window->createSurface(context); + return window->createSurface(context); } void GPUDrawable::present(Context* context) { - window->present(context); + window->present(context); } void GPUDrawable::moveToThread(QThread* targetThread) { - window->moveToThread(targetThread); + window->moveToThread(targetThread); } QSGTexture* GPUDrawable::getTexture() { - return window->getTexture(); + return window->getTexture(); } } // namespace pag diff --git a/src/platform/qt/GPUDrawable.h b/src/platform/qt/GPUDrawable.h index be9ed0440f..9b9a4003d9 100644 --- a/src/platform/qt/GPUDrawable.h +++ b/src/platform/qt/GPUDrawable.h @@ -30,36 +30,36 @@ namespace pag { class QGLWindow; class GPUDrawable : public Drawable { - public: - static std::shared_ptr MakeFrom(QQuickItem* quickItem, - QOpenGLContext* sharedContext = nullptr); +public: + static std::shared_ptr MakeFrom(QQuickItem* quickItem, + QOpenGLContext* sharedContext = nullptr); - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context* context) override; + void present(Context* context) override; - void moveToThread(QThread* targetThread); + void moveToThread(QThread* targetThread); - QSGTexture* getTexture(); + QSGTexture* getTexture(); - private: - int _width = 0; - int _height = 0; - QQuickItem* quickItem = nullptr; - std::shared_ptr window = nullptr; +private: + int _width = 0; + int _height = 0; + QQuickItem* quickItem = nullptr; + std::shared_ptr window = nullptr; - GPUDrawable(QQuickItem* quickItem, std::shared_ptr window); + GPUDrawable(QQuickItem* quickItem, std::shared_ptr window); }; } // namespace pag diff --git a/src/platform/qt/NativeGLDevice.cpp b/src/platform/qt/NativeGLDevice.cpp index 1560667df6..a02cb0868a 100644 --- a/src/platform/qt/NativeGLDevice.cpp +++ b/src/platform/qt/NativeGLDevice.cpp @@ -21,15 +21,15 @@ namespace pag { void* NativeGLDevice::GetCurrentNativeHandle() { - return QOpenGLContext::currentContext(); + return QOpenGLContext::currentContext(); } std::shared_ptr NativeGLDevice::Current() { - return QGLDevice::Current(); + return QGLDevice::Current(); } std::shared_ptr NativeGLDevice::Make(void* sharedContext) { - return QGLDevice::Make(reinterpret_cast(sharedContext)); + return QGLDevice::Make(reinterpret_cast(sharedContext)); } } // namespace pag \ No newline at end of file diff --git a/src/platform/qt/NativePlatform.cpp b/src/platform/qt/NativePlatform.cpp index d6f7a4141c..5ebf7cd58f 100644 --- a/src/platform/qt/NativePlatform.cpp +++ b/src/platform/qt/NativePlatform.cpp @@ -21,7 +21,7 @@ namespace pag { const Platform* Platform::Current() { - static const NativePlatform platform = {}; - return &platform; + static const NativePlatform platform = {}; + return &platform; } } // namespace pag \ No newline at end of file diff --git a/src/platform/qt/NativePlatform.h b/src/platform/qt/NativePlatform.h index 67d59300b3..0177209707 100644 --- a/src/platform/qt/NativePlatform.h +++ b/src/platform/qt/NativePlatform.h @@ -22,6 +22,6 @@ namespace pag { class NativePlatform : public Platform { - public: +public: }; } // namespace pag diff --git a/src/platform/swiftshader/NativeGLDevice.cpp b/src/platform/swiftshader/NativeGLDevice.cpp index e63051b8aa..af092cecff 100644 --- a/src/platform/swiftshader/NativeGLDevice.cpp +++ b/src/platform/swiftshader/NativeGLDevice.cpp @@ -21,15 +21,15 @@ namespace pag { void* NativeGLDevice::GetCurrentNativeHandle() { - return eglGetCurrentContext(); + return eglGetCurrentContext(); } std::shared_ptr NativeGLDevice::Current() { - return EGLDevice::Current(); + return EGLDevice::Current(); } std::shared_ptr NativeGLDevice::Make(void* sharedContext) { - return EGLDevice::Make(sharedContext); + return EGLDevice::Make(sharedContext); } } // namespace pag \ No newline at end of file diff --git a/src/platform/swiftshader/NativePlatform.cpp b/src/platform/swiftshader/NativePlatform.cpp index 5fbc82e325..366d1abf55 100644 --- a/src/platform/swiftshader/NativePlatform.cpp +++ b/src/platform/swiftshader/NativePlatform.cpp @@ -31,92 +31,92 @@ typedef struct FT_LibraryRec_* FT_Library; typedef struct FT_FaceRec_* FT_Face; extern "C" { -static void* ft_alloc(FT_Memory, long size) { - return malloc(static_cast(size)); -} -static void ft_free(FT_Memory, void* block) { - free(block); -} -static void* ft_realloc(FT_Memory, long, long new_size, void* block) { - return realloc(block, static_cast(new_size)); -} + static void* ft_alloc(FT_Memory, long size) { + return malloc(static_cast(size)); + } + static void ft_free(FT_Memory, void* block) { + free(block); + } + static void* ft_realloc(FT_Memory, long, long new_size, void* block) { + return realloc(block, static_cast(new_size)); + } } static FT_MemoryRec_ gFTMemory = {nullptr, ft_alloc, ft_free, ft_realloc}; static std::atomic defaultType = {NALUType::AnnexB}; const Platform* Platform::Current() { - static const NativePlatform platform = {}; - return &platform; + static const NativePlatform platform = {}; + return &platform; } NALUType NativePlatform::naluType() const { - return defaultType; + return defaultType; } void NativePlatform::setNALUType(NALUType type) const { - defaultType = type; + defaultType = type; } static PAGFont ParseFont(const FT_Open_Args* args, int ttcIndex) { - if (args == nullptr) { - return {"", ""}; - } - FT_Library fLibrary = nullptr; - if (FT_New_Library(&gFTMemory, &fLibrary)) { - return {"", ""}; - } - FT_Add_Default_Modules(fLibrary); - FT_Face face; - if (FT_Open_Face(fLibrary, args, ttcIndex, &face)) { + if (args == nullptr) { + return {"", ""}; + } + FT_Library fLibrary = nullptr; + if (FT_New_Library(&gFTMemory, &fLibrary)) { + return {"", ""}; + } + FT_Add_Default_Modules(fLibrary); + FT_Face face; + if (FT_Open_Face(fLibrary, args, ttcIndex, &face)) { + FT_Done_Library(fLibrary); + return {"", ""}; + } + if (face->family_name == nullptr) { + return {"", ""}; + } + std::string fontFamily = face->family_name; + std::string fontStyle = face->style_name; + FT_Done_Face(face); FT_Done_Library(fLibrary); - return {"", ""}; - } - if (face->family_name == nullptr) { - return {"", ""}; - } - std::string fontFamily = face->family_name; - std::string fontStyle = face->style_name; - FT_Done_Face(face); - FT_Done_Library(fLibrary); - return {fontFamily, fontStyle}; + return {fontFamily, fontStyle}; } PAGFont NativePlatform::parseFont(const std::string& fontPath, int ttcIndex) const { - if (fontPath.empty()) { - return {"", ""}; - } - FT_Open_Args args = {}; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_PATHNAME; - args.pathname = const_cast(fontPath.c_str()); - return ParseFont(&args, ttcIndex); + if (fontPath.empty()) { + return {"", ""}; + } + FT_Open_Args args = {}; + memset(&args, 0, sizeof(args)); + args.flags = FT_OPEN_PATHNAME; + args.pathname = const_cast(fontPath.c_str()); + return ParseFont(&args, ttcIndex); } PAGFont NativePlatform::parseFont(const void* data, size_t length, int ttcIndex) const { - if (length == 0) { - return {"", ""}; - } - FT_Open_Args args = {}; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_MEMORY; - args.memory_base = (const FT_Byte*)data; - args.memory_size = static_cast(length); - return ParseFont(&args, ttcIndex); + if (length == 0) { + return {"", ""}; + } + FT_Open_Args args = {}; + memset(&args, 0, sizeof(args)); + args.flags = FT_OPEN_MEMORY; + args.memory_base = (const FT_Byte*)data; + args.memory_size = static_cast(length); + return ParseFont(&args, ttcIndex); } void NativePlatform::traceImage(const PixelMap& pixelMap, const std::string& tag) const { - std::string path = tag; - if (path.empty()) { - path = "TraceImage.png"; - } else if (path.rfind(".png") != path.size() - 4 && path.rfind(".PNG") != path.size() - 4) { - path += ".png"; - } - auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); - if (bytes) { - std::ofstream out(path); - out.write(reinterpret_cast(bytes->data()), bytes->size()); - out.close(); - } + std::string path = tag; + if (path.empty()) { + path = "TraceImage.png"; + } else if (path.rfind(".png") != path.size() - 4 && path.rfind(".PNG") != path.size() - 4) { + path += ".png"; + } + auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); + if (bytes) { + std::ofstream out(path); + out.write(reinterpret_cast(bytes->data()), bytes->size()); + out.close(); + } } } // namespace pag \ No newline at end of file diff --git a/src/platform/swiftshader/NativePlatform.h b/src/platform/swiftshader/NativePlatform.h index 66b64452bf..e394148ddf 100644 --- a/src/platform/swiftshader/NativePlatform.h +++ b/src/platform/swiftshader/NativePlatform.h @@ -22,15 +22,15 @@ namespace pag { class NativePlatform : public Platform { - public: - NALUType naluType() const override; +public: + NALUType naluType() const override; - void setNALUType(NALUType type) const; + void setNALUType(NALUType type) const; - PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; + PAGFont parseFont(const std::string& fontPath, int ttcIndex) const override; - PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; + PAGFont parseFont(const void* data, size_t length, int ttcIndex) const override; - void traceImage(const PixelMap &pixelMap, const std::string &tag) const override; + void traceImage(const PixelMap &pixelMap, const std::string &tag) const override; }; } // namespace pag diff --git a/src/platform/web/GPUDrawable.cpp b/src/platform/web/GPUDrawable.cpp index b0c89f1092..23d48e56c4 100644 --- a/src/platform/web/GPUDrawable.cpp +++ b/src/platform/web/GPUDrawable.cpp @@ -23,34 +23,34 @@ namespace pag { std::shared_ptr GPUDrawable::FromCanvasID(const std::string& canvasID) { - if (canvasID.empty()) { - LOGE("GPUDrawable.FromCanvasID() The canvasID is invalid."); - return nullptr; - } - return std::shared_ptr(new GPUDrawable(canvasID)); + if (canvasID.empty()) { + LOGE("GPUDrawable.FromCanvasID() The canvasID is invalid."); + return nullptr; + } + return std::shared_ptr(new GPUDrawable(canvasID)); } GPUDrawable::GPUDrawable(std::string canvasID) : canvasID(std::move(canvasID)) { - GPUDrawable::updateSize(); + GPUDrawable::updateSize(); } void GPUDrawable::updateSize() { - if (!canvasID.empty()) { - emscripten_get_canvas_element_size(canvasID.c_str(), &_width, &_height); - } + if (!canvasID.empty()) { + emscripten_get_canvas_element_size(canvasID.c_str(), &_width, &_height); + } } std::shared_ptr GPUDrawable::getDevice() { - if (_width <= 0 || _height <= 0) { - return nullptr; - } - if (window == nullptr) { - window = WEBGLWindow::MakeFrom(canvasID); - } - return window->getDevice(); + if (_width <= 0 || _height <= 0) { + return nullptr; + } + if (window == nullptr) { + window = WEBGLWindow::MakeFrom(canvasID); + } + return window->getDevice(); } std::shared_ptr GPUDrawable::createSurface(Context* context) { - return window ? window->createSurface(context) : nullptr; + return window ? window->createSurface(context) : nullptr; } } // namespace pag diff --git a/src/platform/web/GPUDrawable.h b/src/platform/web/GPUDrawable.h index a839daec26..65d69b2090 100644 --- a/src/platform/web/GPUDrawable.h +++ b/src/platform/web/GPUDrawable.h @@ -23,32 +23,32 @@ namespace pag { class GPUDrawable : public Drawable { - public: - static std::shared_ptr FromCanvasID(const std::string& canvasID); +public: + static std::shared_ptr FromCanvasID(const std::string& canvasID); - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context*) override { - } + void present(Context*) override { + } - private: - explicit GPUDrawable(std::string canvasID); +private: + explicit GPUDrawable(std::string canvasID); - std::string canvasID; - int _width = 0; - int _height = 0; - std::shared_ptr window = nullptr; + std::string canvasID; + int _width = 0; + int _height = 0; + std::shared_ptr window = nullptr; }; } // namespace pag diff --git a/src/platform/web/NativeGLDevice.cpp b/src/platform/web/NativeGLDevice.cpp index 3875f19870..863700700f 100644 --- a/src/platform/web/NativeGLDevice.cpp +++ b/src/platform/web/NativeGLDevice.cpp @@ -22,14 +22,14 @@ namespace pag { void* NativeGLDevice::GetCurrentNativeHandle() { - return reinterpret_cast(emscripten_webgl_get_current_context()); + return reinterpret_cast(emscripten_webgl_get_current_context()); } std::shared_ptr NativeGLDevice::Current() { - return WEBGLDevice::Current(); + return WEBGLDevice::Current(); } std::shared_ptr NativeGLDevice::Make(void*) { - return nullptr; + return nullptr; } } // namespace pag diff --git a/src/platform/web/NativeImage.cpp b/src/platform/web/NativeImage.cpp index 3124031177..61155f5f27 100644 --- a/src/platform/web/NativeImage.cpp +++ b/src/platform/web/NativeImage.cpp @@ -24,31 +24,31 @@ using namespace emscripten; namespace pag { std::unique_ptr NativeImage::MakeFrom(const std::shared_ptr& imageBytes) { - auto nativeImageClass = val::module_property("NativeImage"); - if (!nativeImageClass.as()) { - return nullptr; - } - auto bytes = - val(typed_memory_view(imageBytes->size(), static_cast(imageBytes->data()))); - auto nativeImage = nativeImageClass.call("createFromBytes", bytes).await(); - return MakeFrom(nativeImage); + auto nativeImageClass = val::module_property("NativeImage"); + if (!nativeImageClass.as()) { + return nullptr; + } + auto bytes = + val(typed_memory_view(imageBytes->size(), static_cast(imageBytes->data()))); + auto nativeImage = nativeImageClass.call("createFromBytes", bytes).await(); + return MakeFrom(nativeImage); } std::unique_ptr NativeImage::MakeFrom(emscripten::val nativeImage) { - if (!nativeImage.as()) { - return nullptr; - } - auto width = nativeImage.call("width"); - auto height = nativeImage.call("height"); - if (width <= 0 || height <= 0) { - return nullptr; - } - auto image = std::unique_ptr(new NativeImage(width, height)); - image->nativeImage = std::move(nativeImage); - return image; + if (!nativeImage.as()) { + return nullptr; + } + auto width = nativeImage.call("width"); + auto height = nativeImage.call("height"); + if (width <= 0 || height <= 0) { + return nullptr; + } + auto image = std::unique_ptr(new NativeImage(width, height)); + image->nativeImage = std::move(nativeImage); + return image; } std::shared_ptr NativeImage::makeBuffer() const { - return NativeTextureBuffer::Make(width(), height(), nativeImage); + return NativeTextureBuffer::Make(width(), height(), nativeImage); } } // namespace pag diff --git a/src/platform/web/NativeImage.h b/src/platform/web/NativeImage.h index d66a125e58..b1d4e9b076 100644 --- a/src/platform/web/NativeImage.h +++ b/src/platform/web/NativeImage.h @@ -24,22 +24,22 @@ namespace pag { class NativeImage : public Image { - public: - public: - static std::unique_ptr MakeFrom(const std::shared_ptr& imageBytes); +public: +public: + static std::unique_ptr MakeFrom(const std::shared_ptr& imageBytes); - static std::unique_ptr MakeFrom(emscripten::val nativeImage); + static std::unique_ptr MakeFrom(emscripten::val nativeImage); - std::shared_ptr makeBuffer() const override; + std::shared_ptr makeBuffer() const override; - bool readPixels(const ImageInfo& /*dstInfo*/, void* /*dstPixels*/) const override { - return false; - } + bool readPixels(const ImageInfo& /*dstInfo*/, void* /*dstPixels*/) const override { + return false; + } - private: - emscripten::val nativeImage = emscripten::val::null(); +private: + emscripten::val nativeImage = emscripten::val::null(); - NativeImage(int width, int height) : Image(width, height, Orientation::TopLeft) { - } + NativeImage(int width, int height) : Image(width, height, Orientation::TopLeft) { + } }; } // namespace pag diff --git a/src/platform/web/NativePlatform.cpp b/src/platform/web/NativePlatform.cpp index c7d93f8870..a43fba2901 100644 --- a/src/platform/web/NativePlatform.cpp +++ b/src/platform/web/NativePlatform.cpp @@ -26,18 +26,18 @@ using namespace emscripten; namespace pag { const Platform* Platform::Current() { - static const NativePlatform platform = {}; - return &platform; + static const NativePlatform platform = {}; + return &platform; } std::shared_ptr NativePlatform::makeImage(std::shared_ptr imageBytes) const { - return NativeImage::MakeFrom(imageBytes); + return NativeImage::MakeFrom(imageBytes); } void NativePlatform::traceImage(const PixelMap& pixelMap, const std::string& tag) const { - auto traceImage = val::module_property("traceImage"); - auto bytes = val(typed_memory_view(pixelMap.info().rowBytes() * pixelMap.info().height(), - static_cast(pixelMap.pixels()))); - traceImage(pixelMap.info(), bytes, tag); + auto traceImage = val::module_property("traceImage"); + auto bytes = val(typed_memory_view(pixelMap.info().rowBytes() * pixelMap.info().height(), + static_cast(pixelMap.pixels()))); + traceImage(pixelMap.info(), bytes, tag); } } // namespace pag diff --git a/src/platform/web/NativePlatform.h b/src/platform/web/NativePlatform.h index b0f7fbc212..3321911134 100644 --- a/src/platform/web/NativePlatform.h +++ b/src/platform/web/NativePlatform.h @@ -22,9 +22,9 @@ namespace pag { class NativePlatform : public Platform { - public: - std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; +public: + std::shared_ptr makeImage(std::shared_ptr imageBytes) const override; - void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; + void traceImage(const PixelMap& pixelMap, const std::string& tag) const override; }; } // namespace pag diff --git a/src/platform/web/NativeTextureBuffer.cpp b/src/platform/web/NativeTextureBuffer.cpp index 40042df653..8a04096388 100644 --- a/src/platform/web/NativeTextureBuffer.cpp +++ b/src/platform/web/NativeTextureBuffer.cpp @@ -24,22 +24,22 @@ using namespace emscripten; namespace pag { std::shared_ptr NativeTextureBuffer::Make(int width, int height, val source) { - if (!source.as()) { - return nullptr; - } - return std::shared_ptr( - new NativeTextureBuffer(width, height, std::move(source))); + if (!source.as()) { + return nullptr; + } + return std::shared_ptr( + new NativeTextureBuffer(width, height, std::move(source))); } std::shared_ptr NativeTextureBuffer::makeTexture(Context* context) const { - auto texture = Texture::MakeRGBA(context, width(), height(), nullptr, 0); - if (texture == nullptr) { - return nullptr; - } - auto& glInfo = std::static_pointer_cast(texture)->getGLInfo(); - const auto* gl = GLContext::Unwrap(context); - gl->bindTexture(glInfo.target, glInfo.id); - source.call("upload", val::module_property("GL")); - return texture; + auto texture = Texture::MakeRGBA(context, width(), height(), nullptr, 0); + if (texture == nullptr) { + return nullptr; + } + auto& glInfo = std::static_pointer_cast(texture)->getGLInfo(); + const auto* gl = GLContext::Unwrap(context); + gl->bindTexture(glInfo.target, glInfo.id); + source.call("upload", val::module_property("GL")); + return texture; } } // namespace pag diff --git a/src/platform/web/NativeTextureBuffer.h b/src/platform/web/NativeTextureBuffer.h index 8249c55b50..d21d895ec8 100644 --- a/src/platform/web/NativeTextureBuffer.h +++ b/src/platform/web/NativeTextureBuffer.h @@ -24,16 +24,16 @@ namespace pag { class NativeTextureBuffer : public TextureBuffer { - public: - static std::shared_ptr Make(int width, int height, emscripten::val source); +public: + static std::shared_ptr Make(int width, int height, emscripten::val source); - std::shared_ptr makeTexture(Context* context) const override; + std::shared_ptr makeTexture(Context* context) const override; - private: - explicit NativeTextureBuffer(int width, int height, emscripten::val source) - : TextureBuffer(width, height), source(source) { - } +private: + explicit NativeTextureBuffer(int width, int height, emscripten::val source) + : TextureBuffer(width, height), source(source) { + } - emscripten::val source = emscripten::val::null(); + emscripten::val source = emscripten::val::null(); }; } // namespace pag diff --git a/src/platform/web/VideoSequenceReader.cpp b/src/platform/web/VideoSequenceReader.cpp index 1194d468f5..01f48742e4 100644 --- a/src/platform/web/VideoSequenceReader.cpp +++ b/src/platform/web/VideoSequenceReader.cpp @@ -26,67 +26,67 @@ using namespace emscripten; namespace pag { std::shared_ptr SequenceReader::Make(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy policy) { - return std::make_shared(std::move(file), sequence, policy); + return std::make_shared(std::move(file), sequence, policy); } VideoSequenceReader::VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, - DecodingPolicy) + DecodingPolicy) : SequenceReader(std::move(file), sequence) { - width = sequence->alphaStartX + sequence->width; - if (width % 2 == 1) { - width++; - } - height = sequence->alphaStartY + sequence->height; - if (height % 2 == 1) { - height++; - } - auto videoReaderClass = val::module_property("VideoReader"); - if (videoReaderClass.as()) { - auto headers = val::array(); - for (auto* header: sequence->headers) { - headers.call("push", val(typed_memory_view(header->length(), header->data()))); + width = sequence->alphaStartX + sequence->width; + if (width % 2 == 1) { + width++; } - auto frames = val::array(); - auto ptsList = val::array(); - for (auto* frame: sequence->frames) { - frames.call( - "push", val(typed_memory_view(frame->fileBytes->length(), frame->fileBytes->data()))); - ptsList.call("push", static_cast(frame->frame)); + height = sequence->alphaStartY + sequence->height; + if (height % 2 == 1) { + height++; + } + auto videoReaderClass = val::module_property("VideoReader"); + if (videoReaderClass.as()) { + auto headers = val::array(); + for (auto* header: sequence->headers) { + headers.call("push", val(typed_memory_view(header->length(), header->data()))); + } + auto frames = val::array(); + auto ptsList = val::array(); + for (auto* frame: sequence->frames) { + frames.call( + "push", val(typed_memory_view(frame->fileBytes->length(), frame->fileBytes->data()))); + ptsList.call("push", static_cast(frame->frame)); + } + videoReader = + videoReaderClass.new_(width, height, sequence->frameRate, headers, frames, ptsList); } - videoReader = - videoReaderClass.new_(width, height, sequence->frameRate, headers, frames, ptsList); - } } VideoSequenceReader::~VideoSequenceReader() { - if (videoReader.as()) { - videoReader.call("onDestroy"); - } + if (videoReader.as()) { + videoReader.call("onDestroy"); + } } void VideoSequenceReader::prepareAsync(Frame targetFrame) { - // Web 端没有异步初始化解码器,也没有预测。 - // 这个方法是 Graphic->prepare() 每次调用的。 - // Web 端渲染过程不能 await,否则会把渲染一半的 Canvas 上屏。 - if (videoReader.as()) { - videoReader.call("prepareAsync", static_cast(targetFrame)).await(); - } + // Web 端没有异步初始化解码器,也没有预测。 + // 这个方法是 Graphic->prepare() 每次调用的。 + // Web 端渲染过程不能 await,否则会把渲染一半的 Canvas 上屏。 + if (videoReader.as()) { + videoReader.call("prepareAsync", static_cast(targetFrame)).await(); + } } std::shared_ptr VideoSequenceReader::readTexture(Frame targetFrame, RenderCache* cache) { - if (!videoReader.as()) { - return nullptr; - } - if (targetFrame == lastFrame) { + if (!videoReader.as()) { + return nullptr; + } + if (targetFrame == lastFrame) { + return texture; + } + GLStateGuard stateGuard(cache->getContext()); + if (texture == nullptr) { + texture = GLTexture::MakeRGBA(cache->getContext(), width, height); + } + auto& glInfo = std::static_pointer_cast(texture)->getGLInfo(); + videoReader.call("renderToTexture", val::module_property("GL"), glInfo.id); + lastFrame = targetFrame; return texture; - } - GLStateGuard stateGuard(cache->getContext()); - if (texture == nullptr) { - texture = GLTexture::MakeRGBA(cache->getContext(), width, height); - } - auto& glInfo = std::static_pointer_cast(texture)->getGLInfo(); - videoReader.call("renderToTexture", val::module_property("GL"), glInfo.id); - lastFrame = targetFrame; - return texture; } } // namespace pag diff --git a/src/platform/web/VideoSequenceReader.h b/src/platform/web/VideoSequenceReader.h index c76818a9ba..021814e8ee 100644 --- a/src/platform/web/VideoSequenceReader.h +++ b/src/platform/web/VideoSequenceReader.h @@ -24,20 +24,20 @@ namespace pag { class VideoSequenceReader : public SequenceReader { - public: - VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy); +public: + VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy); - ~VideoSequenceReader() override; + ~VideoSequenceReader() override; - void prepareAsync(Frame targetFrame) override; + void prepareAsync(Frame targetFrame) override; - std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) override; + std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) override; - private: - Frame lastFrame = -1; - emscripten::val videoReader = emscripten::val::null(); - std::shared_ptr texture = nullptr; - int32_t width = 0; - int32_t height = 0; +private: + Frame lastFrame = -1; + emscripten::val videoReader = emscripten::val::null(); + std::shared_ptr texture = nullptr; + int32_t width = 0; + int32_t height = 0; }; } // namespace pag diff --git a/src/platform/win/GPUDrawable.cpp b/src/platform/win/GPUDrawable.cpp index 0db122d7e2..adabde5d9d 100644 --- a/src/platform/win/GPUDrawable.cpp +++ b/src/platform/win/GPUDrawable.cpp @@ -23,47 +23,47 @@ namespace pag { std::shared_ptr GPUDrawable::FromWindow(void* nativeWindow, void* sharedContext) { - if (nativeWindow == nullptr) { - LOGE("GPUDrawable.FromWindow() The nativeWindow is invalid."); - return nullptr; - } - return std::shared_ptr(new GPUDrawable(nativeWindow, sharedContext)); + if (nativeWindow == nullptr) { + LOGE("GPUDrawable.FromWindow() The nativeWindow is invalid."); + return nullptr; + } + return std::shared_ptr(new GPUDrawable(nativeWindow, sharedContext)); } GPUDrawable::GPUDrawable(void* nativeWindow, void* sharedContext) : nativeWindow(nativeWindow), sharedContext(sharedContext) { - GPUDrawable::updateSize(); + GPUDrawable::updateSize(); } void GPUDrawable::updateSize() { - if (nativeWindow != nullptr) { - RECT rect = {}; - if (GetWindowRect(static_cast(nativeWindow), &rect)) { - _width = rect.right - rect.left; - _height = rect.bottom - rect.top; - } else { - _width = 0; - _height = 0; + if (nativeWindow != nullptr) { + RECT rect = {}; + if (GetWindowRect(static_cast(nativeWindow), &rect)) { + _width = rect.right - rect.left; + _height = rect.bottom - rect.top; + } else { + _width = 0; + _height = 0; + } } - } } std::shared_ptr GPUDrawable::getDevice() { - if (_width <= 0 || _height <= 0) { - return nullptr; - } - if (window == nullptr) { - window = - EGLWindow::MakeFrom(reinterpret_cast(nativeWindow), sharedContext); - } - return window ? window->getDevice() : nullptr; + if (_width <= 0 || _height <= 0) { + return nullptr; + } + if (window == nullptr) { + window = + EGLWindow::MakeFrom(reinterpret_cast(nativeWindow), sharedContext); + } + return window ? window->getDevice() : nullptr; } std::shared_ptr GPUDrawable::createSurface(Context* context) { - return window ? window->createSurface(context) : nullptr; + return window ? window->createSurface(context) : nullptr; } void GPUDrawable::present(Context* context) { - window->present(context); + window->present(context); } } // namespace pag diff --git a/src/platform/win/GPUDrawable.h b/src/platform/win/GPUDrawable.h index 489f7a6e7b..e27e878649 100644 --- a/src/platform/win/GPUDrawable.h +++ b/src/platform/win/GPUDrawable.h @@ -24,32 +24,32 @@ namespace pag { class EGLWindow; class GPUDrawable : public Drawable { - public: - static std::shared_ptr FromWindow(void* nativeWindow, void* sharedContext = nullptr); +public: + static std::shared_ptr FromWindow(void* nativeWindow, void* sharedContext = nullptr); - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override; + void updateSize() override; - std::shared_ptr getDevice() override; + std::shared_ptr getDevice() override; - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context* context) override; + void present(Context* context) override; - private: - int _width = 0; - int _height = 0; - std::shared_ptr window = nullptr; - void* nativeWindow = nullptr; - void* sharedContext = nullptr; +private: + int _width = 0; + int _height = 0; + std::shared_ptr window = nullptr; + void* nativeWindow = nullptr; + void* sharedContext = nullptr; - GPUDrawable(void* nativeWindow, void* sharedContext); + GPUDrawable(void* nativeWindow, void* sharedContext); }; } // namespace pag diff --git a/src/platform/win/NativeGLDevice.cpp b/src/platform/win/NativeGLDevice.cpp index e63051b8aa..af092cecff 100644 --- a/src/platform/win/NativeGLDevice.cpp +++ b/src/platform/win/NativeGLDevice.cpp @@ -21,15 +21,15 @@ namespace pag { void* NativeGLDevice::GetCurrentNativeHandle() { - return eglGetCurrentContext(); + return eglGetCurrentContext(); } std::shared_ptr NativeGLDevice::Current() { - return EGLDevice::Current(); + return EGLDevice::Current(); } std::shared_ptr NativeGLDevice::Make(void* sharedContext) { - return EGLDevice::Make(sharedContext); + return EGLDevice::Make(sharedContext); } } // namespace pag \ No newline at end of file diff --git a/src/platform/win/NativePlatform.cpp b/src/platform/win/NativePlatform.cpp index d6f7a4141c..5ebf7cd58f 100644 --- a/src/platform/win/NativePlatform.cpp +++ b/src/platform/win/NativePlatform.cpp @@ -21,7 +21,7 @@ namespace pag { const Platform* Platform::Current() { - static const NativePlatform platform = {}; - return &platform; + static const NativePlatform platform = {}; + return &platform; } } // namespace pag \ No newline at end of file diff --git a/src/platform/win/NativePlatform.h b/src/platform/win/NativePlatform.h index 67d59300b3..0177209707 100644 --- a/src/platform/win/NativePlatform.h +++ b/src/platform/win/NativePlatform.h @@ -22,6 +22,6 @@ namespace pag { class NativePlatform : public Platform { - public: +public: }; } // namespace pag diff --git a/src/rendering/Drawable.cpp b/src/rendering/Drawable.cpp index 3be4787de0..7468953d74 100644 --- a/src/rendering/Drawable.cpp +++ b/src/rendering/Drawable.cpp @@ -20,13 +20,13 @@ namespace pag { RenderTargetDrawable::RenderTargetDrawable(std::shared_ptr device, - const BackendRenderTarget& renderTarget, - ImageOrigin origin) + const BackendRenderTarget& renderTarget, + ImageOrigin origin) : device(std::move(device)), renderTarget(renderTarget), origin(origin) { } std::shared_ptr RenderTargetDrawable::createSurface(Context* context) { - return Surface::MakeFrom(context, renderTarget, origin); + return Surface::MakeFrom(context, renderTarget, origin); } TextureDrawable::TextureDrawable(std::shared_ptr device, const BackendTexture& texture, @@ -35,7 +35,7 @@ TextureDrawable::TextureDrawable(std::shared_ptr device, const BackendTe } std::shared_ptr TextureDrawable::createSurface(Context* context) { - return Surface::MakeFrom(context, texture, origin); + return Surface::MakeFrom(context, texture, origin); } OffscreenDrawable::OffscreenDrawable(int width, int height, std::shared_ptr device) @@ -43,6 +43,6 @@ OffscreenDrawable::OffscreenDrawable(int width, int height, std::shared_ptr OffscreenDrawable::createSurface(Context* context) { - return Surface::Make(context, _width, _height); + return Surface::Make(context, _width, _height); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/Drawable.h b/src/rendering/Drawable.h index 27dcfad125..647f92fa15 100644 --- a/src/rendering/Drawable.h +++ b/src/rendering/Drawable.h @@ -23,94 +23,94 @@ namespace pag { class RenderTargetDrawable : public Drawable { - public: - RenderTargetDrawable(std::shared_ptr device, const BackendRenderTarget& renderTarget, - ImageOrigin origin); +public: + RenderTargetDrawable(std::shared_ptr device, const BackendRenderTarget& renderTarget, + ImageOrigin origin); - int width() const override { - return renderTarget.width(); - } + int width() const override { + return renderTarget.width(); + } - int height() const override { - return renderTarget.height(); - } + int height() const override { + return renderTarget.height(); + } - void updateSize() override { - } + void updateSize() override { + } - std::shared_ptr getDevice() override { - return device; - } + std::shared_ptr getDevice() override { + return device; + } - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context*) override { - } + void present(Context*) override { + } - private: - std::shared_ptr device = nullptr; - BackendRenderTarget renderTarget = {}; - ImageOrigin origin = ImageOrigin::TopLeft; +private: + std::shared_ptr device = nullptr; + BackendRenderTarget renderTarget = {}; + ImageOrigin origin = ImageOrigin::TopLeft; }; class TextureDrawable : public Drawable { - public: - TextureDrawable(std::shared_ptr device, const BackendTexture& texture, - ImageOrigin origin); +public: + TextureDrawable(std::shared_ptr device, const BackendTexture& texture, + ImageOrigin origin); - int width() const override { - return texture.width(); - } + int width() const override { + return texture.width(); + } - int height() const override { - return texture.height(); - } + int height() const override { + return texture.height(); + } - void updateSize() override { - } + void updateSize() override { + } - std::shared_ptr getDevice() override { - return device; - } + std::shared_ptr getDevice() override { + return device; + } - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context*) override { - } + void present(Context*) override { + } - private: - std::shared_ptr device = nullptr; - BackendTexture texture = {}; - ImageOrigin origin = ImageOrigin::TopLeft; +private: + std::shared_ptr device = nullptr; + BackendTexture texture = {}; + ImageOrigin origin = ImageOrigin::TopLeft; }; class OffscreenDrawable : public Drawable { - public: - OffscreenDrawable(int width, int height, std::shared_ptr device); +public: + OffscreenDrawable(int width, int height, std::shared_ptr device); - int width() const override { - return _width; - } + int width() const override { + return _width; + } - int height() const override { - return _height; - } + int height() const override { + return _height; + } - void updateSize() override { - } + void updateSize() override { + } - std::shared_ptr getDevice() override { - return device; - } + std::shared_ptr getDevice() override { + return device; + } - std::shared_ptr createSurface(Context* context) override; + std::shared_ptr createSurface(Context* context) override; - void present(Context*) override { - } + void present(Context*) override { + } - private: - int _width = 0; - int _height = 0; - std::shared_ptr device = nullptr; +private: + int _width = 0; + int _height = 0; + std::shared_ptr device = nullptr; }; } // namespace pag diff --git a/src/rendering/FileReporter.cpp b/src/rendering/FileReporter.cpp index e4a2b27777..fba31eee71 100644 --- a/src/rendering/FileReporter.cpp +++ b/src/rendering/FileReporter.cpp @@ -24,138 +24,138 @@ namespace pag { int64_t GetAverage(int64_t totalData, int count) { - if (totalData == 0 || count == 0) { - return 0; - } - return totalData / count; + if (totalData == 0 || count == 0) { + return 0; + } + return totalData / count; } std::unique_ptr FileReporter::Make(std::shared_ptr pagLayer) { - FileReporter* reporter = nullptr; - while (pagLayer) { - auto file = pagLayer->getFile(); - if (file) { - reporter = new FileReporter(file.get()); - break; - } - if (pagLayer->layerType() != LayerType::PreCompose || - std::static_pointer_cast(pagLayer)->layers.empty()) { - break; + FileReporter* reporter = nullptr; + while (pagLayer) { + auto file = pagLayer->getFile(); + if (file) { + reporter = new FileReporter(file.get()); + break; + } + if (pagLayer->layerType() != LayerType::PreCompose || + std::static_pointer_cast(pagLayer)->layers.empty()) { + break; + } + pagLayer = std::static_pointer_cast(pagLayer)->layers.front(); } - pagLayer = std::static_pointer_cast(pagLayer)->layers.front(); - } - return std::unique_ptr(reporter); + return std::unique_ptr(reporter); } FileReporter::FileReporter(File* file) { - setFileInfo(file); + setFileInfo(file); } FileReporter::~FileReporter() { - reportData(); + reportData(); } void FileReporter::setFileInfo(File* file) { - auto frameRate = static_cast(file->frameRate()); - std::string separator = "|"; - pagInfoString = - file->path + separator + std::to_string(frameRate) + separator + - std::to_string(file->duration()) + separator + std::to_string(file->width()) + separator + - std::to_string(file->height()) + separator + std::to_string(file->numLayers()) + separator + - std::to_string(file->numVideos()) + separator + std::to_string(file->tagLevel()) + separator; + auto frameRate = static_cast(file->frameRate()); + std::string separator = "|"; + pagInfoString = + file->path + separator + std::to_string(frameRate) + separator + + std::to_string(file->duration()) + separator + std::to_string(file->width()) + separator + + std::to_string(file->height()) + separator + std::to_string(file->numLayers()) + separator + + std::to_string(file->numVideos()) + separator + std::to_string(file->tagLevel()) + separator; } void FileReporter::reportData() { - std::unordered_map reportInfos; - reportInfos.insert( - std::make_pair("presentFirstFrameTime", std::to_string(presentFirstFrameTime))); - reportInfos.insert(std::make_pair("presentMaxTime", std::to_string(presentMaxTime))); - reportInfos.insert(std::make_pair("presentAverageTime", - std::to_string(GetAverage(presentTotalTime, flushCount - 1)))); - reportInfos.insert(std::make_pair("renderFirstFrameTime", std::to_string(renderFirstFrameTime))); - reportInfos.insert(std::make_pair("renderMaxTime", std::to_string(renderMaxTime))); - reportInfos.insert(std::make_pair("renderAverageTime", - std::to_string(GetAverage(renderTotalTime, flushCount - 1)))); - reportInfos.insert(std::make_pair("flushFirstFrameTime", std::to_string(flushFirstFrameTime))); - reportInfos.insert(std::make_pair("flushMaxTime", std::to_string(flushMaxTime))); - reportInfos.insert(std::make_pair("flushAverageTime", - std::to_string(GetAverage(flushTotalTime, flushCount - 1)))); - - reportInfos.insert(std::make_pair("imageDecodingMaxTime", std::to_string(imageDecodingMaxTime))); - reportInfos.insert( - std::make_pair("hardwareDecodingInitialTime", std::to_string(hardwareDecodingInitialTime))); - reportInfos.insert( - std::make_pair("hardwareDecodingMaxTime", std::to_string(hardwareDecodingMaxTime))); - reportInfos.insert( - std::make_pair("hardwareDecodingAverageTime", - std::to_string(GetAverage(hardwareDecodingTotalTime, hardwareDecodingCount)))); - reportInfos.insert( - std::make_pair("softwareDecodingInitialTime", std::to_string(softwareDecodingInitialTime))); - reportInfos.insert( - std::make_pair("softwareDecodingMaxTime", std::to_string(softwareDecodingMaxTime))); - reportInfos.insert( - std::make_pair("softwareDecodingAverageTime", - std::to_string(GetAverage(softwareDecodingTotalTime, softwareDecodingCount)))); - reportInfos.insert(std::make_pair("graphicsMemoryMax", std::to_string(graphicsMemoryMax))); - reportInfos.insert(std::make_pair("graphicsMemoryAverage", - std::to_string(GetAverage(graphicsMemoryTotal, flushCount)))); - reportInfos.insert(std::make_pair("flushCount", std::to_string(flushCount))); - reportInfos.insert(std::make_pair("pagInfo", pagInfoString)); - reportInfos.insert(std::make_pair("event", "pag_monitor")); - reportInfos.insert(std::make_pair("version", PAG::SDKVersion())); - reportInfos.insert(std::make_pair("usability", "1")); - Platform::Current()->reportStatisticalData(reportInfos); + std::unordered_map reportInfos; + reportInfos.insert( + std::make_pair("presentFirstFrameTime", std::to_string(presentFirstFrameTime))); + reportInfos.insert(std::make_pair("presentMaxTime", std::to_string(presentMaxTime))); + reportInfos.insert(std::make_pair("presentAverageTime", + std::to_string(GetAverage(presentTotalTime, flushCount - 1)))); + reportInfos.insert(std::make_pair("renderFirstFrameTime", std::to_string(renderFirstFrameTime))); + reportInfos.insert(std::make_pair("renderMaxTime", std::to_string(renderMaxTime))); + reportInfos.insert(std::make_pair("renderAverageTime", + std::to_string(GetAverage(renderTotalTime, flushCount - 1)))); + reportInfos.insert(std::make_pair("flushFirstFrameTime", std::to_string(flushFirstFrameTime))); + reportInfos.insert(std::make_pair("flushMaxTime", std::to_string(flushMaxTime))); + reportInfos.insert(std::make_pair("flushAverageTime", + std::to_string(GetAverage(flushTotalTime, flushCount - 1)))); + + reportInfos.insert(std::make_pair("imageDecodingMaxTime", std::to_string(imageDecodingMaxTime))); + reportInfos.insert( + std::make_pair("hardwareDecodingInitialTime", std::to_string(hardwareDecodingInitialTime))); + reportInfos.insert( + std::make_pair("hardwareDecodingMaxTime", std::to_string(hardwareDecodingMaxTime))); + reportInfos.insert( + std::make_pair("hardwareDecodingAverageTime", + std::to_string(GetAverage(hardwareDecodingTotalTime, hardwareDecodingCount)))); + reportInfos.insert( + std::make_pair("softwareDecodingInitialTime", std::to_string(softwareDecodingInitialTime))); + reportInfos.insert( + std::make_pair("softwareDecodingMaxTime", std::to_string(softwareDecodingMaxTime))); + reportInfos.insert( + std::make_pair("softwareDecodingAverageTime", + std::to_string(GetAverage(softwareDecodingTotalTime, softwareDecodingCount)))); + reportInfos.insert(std::make_pair("graphicsMemoryMax", std::to_string(graphicsMemoryMax))); + reportInfos.insert(std::make_pair("graphicsMemoryAverage", + std::to_string(GetAverage(graphicsMemoryTotal, flushCount)))); + reportInfos.insert(std::make_pair("flushCount", std::to_string(flushCount))); + reportInfos.insert(std::make_pair("pagInfo", pagInfoString)); + reportInfos.insert(std::make_pair("event", "pag_monitor")); + reportInfos.insert(std::make_pair("version", PAG::SDKVersion())); + reportInfos.insert(std::make_pair("usability", "1")); + Platform::Current()->reportStatisticalData(reportInfos); } static int64_t GetOldRenderTime(RenderCache* cache) { - // 性能统计增加了数据字段,部分含义发生了改变,这里拼装出原先的 - // renderingTime,确保数据上报结果跟之前一致。 - return cache->totalTime - cache->presentingTime - cache->imageDecodingTime; + // 性能统计增加了数据字段,部分含义发生了改变,这里拼装出原先的 + // renderingTime,确保数据上报结果跟之前一致。 + return cache->totalTime - cache->presentingTime - cache->imageDecodingTime; } void FileReporter::recordPerformance(RenderCache* cache) { - flushCount++; - - if (presentFirstFrameTime == 0) { - presentFirstFrameTime = cache->presentingTime; - } else { - presentMaxTime = std::max(presentMaxTime, cache->presentingTime); - presentTotalTime += cache->presentingTime; - } - - if (renderFirstFrameTime == 0) { - renderFirstFrameTime = GetOldRenderTime(cache); - } else { - renderMaxTime = std::max(renderMaxTime, GetOldRenderTime(cache)); - renderTotalTime += GetOldRenderTime(cache); - } - - if (flushFirstFrameTime == 0) { - flushFirstFrameTime = presentFirstFrameTime + renderFirstFrameTime; - } else { - flushMaxTime = std::max(flushMaxTime, cache->presentingTime + GetOldRenderTime(cache)); - flushTotalTime = presentTotalTime + renderTotalTime; - } - - if (cache->softwareDecodingTime > 0) { - softwareDecodingMaxTime = std::max(softwareDecodingMaxTime, cache->softwareDecodingTime); - softwareDecodingTotalTime += cache->softwareDecodingTime; - softwareDecodingCount++; - } - - if (cache->hardwareDecodingTime > 0) { - hardwareDecodingMaxTime = std::max(hardwareDecodingMaxTime, cache->hardwareDecodingTime); - hardwareDecodingTotalTime += cache->hardwareDecodingTime; - hardwareDecodingCount++; - } - - imageDecodingMaxTime = std::max(imageDecodingMaxTime, cache->imageDecodingTime); - graphicsMemoryMax = std::max(graphicsMemoryMax, cache->memoryUsage()); - graphicsMemoryTotal += cache->memoryUsage(); - softwareDecodingInitialTime = - std::max(softwareDecodingInitialTime, cache->softwareDecodingInitialTime); - hardwareDecodingInitialTime = - std::max(hardwareDecodingInitialTime, cache->hardwareDecodingInitialTime); + flushCount++; + + if (presentFirstFrameTime == 0) { + presentFirstFrameTime = cache->presentingTime; + } else { + presentMaxTime = std::max(presentMaxTime, cache->presentingTime); + presentTotalTime += cache->presentingTime; + } + + if (renderFirstFrameTime == 0) { + renderFirstFrameTime = GetOldRenderTime(cache); + } else { + renderMaxTime = std::max(renderMaxTime, GetOldRenderTime(cache)); + renderTotalTime += GetOldRenderTime(cache); + } + + if (flushFirstFrameTime == 0) { + flushFirstFrameTime = presentFirstFrameTime + renderFirstFrameTime; + } else { + flushMaxTime = std::max(flushMaxTime, cache->presentingTime + GetOldRenderTime(cache)); + flushTotalTime = presentTotalTime + renderTotalTime; + } + + if (cache->softwareDecodingTime > 0) { + softwareDecodingMaxTime = std::max(softwareDecodingMaxTime, cache->softwareDecodingTime); + softwareDecodingTotalTime += cache->softwareDecodingTime; + softwareDecodingCount++; + } + + if (cache->hardwareDecodingTime > 0) { + hardwareDecodingMaxTime = std::max(hardwareDecodingMaxTime, cache->hardwareDecodingTime); + hardwareDecodingTotalTime += cache->hardwareDecodingTime; + hardwareDecodingCount++; + } + + imageDecodingMaxTime = std::max(imageDecodingMaxTime, cache->imageDecodingTime); + graphicsMemoryMax = std::max(graphicsMemoryMax, cache->memoryUsage()); + graphicsMemoryTotal += cache->memoryUsage(); + softwareDecodingInitialTime = + std::max(softwareDecodingInitialTime, cache->softwareDecodingInitialTime); + hardwareDecodingInitialTime = + std::max(hardwareDecodingInitialTime, cache->hardwareDecodingInitialTime); } } // namespace pag diff --git a/src/rendering/FileReporter.h b/src/rendering/FileReporter.h index 84e42ec7eb..d8d8ec4526 100644 --- a/src/rendering/FileReporter.h +++ b/src/rendering/FileReporter.h @@ -25,45 +25,45 @@ namespace pag { class FileReporter { - public: - static std::unique_ptr Make(std::shared_ptr pagLayer); +public: + static std::unique_ptr Make(std::shared_ptr pagLayer); - explicit FileReporter(File* file); - ~FileReporter(); - void recordPerformance(RenderCache* cache); + explicit FileReporter(File* file); + ~FileReporter(); + void recordPerformance(RenderCache* cache); - private: - void setFileInfo(File* file); - void reportData(); +private: + void setFileInfo(File* file); + void reportData(); - std::string pagInfoString; - int flushCount = 0; + std::string pagInfoString; + int flushCount = 0; - int64_t presentTotalTime = 0; - int64_t presentMaxTime = 0; - int64_t presentFirstFrameTime = 0; + int64_t presentTotalTime = 0; + int64_t presentMaxTime = 0; + int64_t presentFirstFrameTime = 0; - int64_t renderTotalTime = 0; - int64_t renderMaxTime = 0; - int64_t renderFirstFrameTime = 0; + int64_t renderTotalTime = 0; + int64_t renderMaxTime = 0; + int64_t renderFirstFrameTime = 0; - int64_t flushTotalTime = 0; - int64_t flushMaxTime = 0; - int64_t flushFirstFrameTime = 0; + int64_t flushTotalTime = 0; + int64_t flushMaxTime = 0; + int64_t flushFirstFrameTime = 0; - int64_t imageDecodingMaxTime = 0; + int64_t imageDecodingMaxTime = 0; - int64_t hardwareDecodingMaxTime = 0; - int64_t hardwareDecodingTotalTime = 0; - int64_t hardwareDecodingInitialTime = 0; - int hardwareDecodingCount = 0; + int64_t hardwareDecodingMaxTime = 0; + int64_t hardwareDecodingTotalTime = 0; + int64_t hardwareDecodingInitialTime = 0; + int hardwareDecodingCount = 0; - int64_t softwareDecodingTotalTime = 0; - int64_t softwareDecodingMaxTime = 0; - int64_t softwareDecodingInitialTime = 0; - int softwareDecodingCount = 0; + int64_t softwareDecodingTotalTime = 0; + int64_t softwareDecodingMaxTime = 0; + int64_t softwareDecodingInitialTime = 0; + int softwareDecodingCount = 0; - size_t graphicsMemoryMax = 0; - size_t graphicsMemoryTotal = 0; + size_t graphicsMemoryMax = 0; + size_t graphicsMemoryTotal = 0; }; } // namespace pag diff --git a/src/rendering/PAG.cpp b/src/rendering/PAG.cpp index f71a3a075e..d82735f557 100644 --- a/src/rendering/PAG.cpp +++ b/src/rendering/PAG.cpp @@ -23,6 +23,6 @@ namespace pag { static const char sdkVersion[] = "4.0.0.1"; std::string PAG::SDKVersion() { - return sdkVersion; + return sdkVersion; } } // namespace pag diff --git a/src/rendering/PAGFile.cpp b/src/rendering/PAGFile.cpp index 8614ae4cc4..429556f3e5 100644 --- a/src/rendering/PAGFile.cpp +++ b/src/rendering/PAGFile.cpp @@ -25,372 +25,385 @@ namespace pag { uint16_t PAGFile::MaxSupportedTagLevel() { - return File::MaxSupportedTagLevel(); + return File::MaxSupportedTagLevel(); } std::shared_ptr PAGFile::Load(const void* bytes, size_t length, const std::string& filePath) { - auto file = File::Load(bytes, length, filePath); - return MakeFrom(file); + auto file = File::Load(bytes, length, filePath); + return MakeFrom(file); } std::shared_ptr PAGFile::Load(const std::string& filePath) { - auto file = File::Load(filePath); - return MakeFrom(file); + auto file = File::Load(filePath); + return MakeFrom(file); } std::shared_ptr PAGFile::MakeFrom(std::shared_ptr file) { - if (file == nullptr) { - return nullptr; - } - auto pagLayer = BuildPAGLayer(file, file->getRootLayer()); - auto locker = std::make_shared(); - pagLayer->updateRootLocker(locker); - if (pagLayer->layerType() != LayerType::PreCompose) { - return nullptr; - } - pagLayer->gotoTime(0); - auto pagFile = std::static_pointer_cast(pagLayer); - pagFile->onAddToRootFile(pagFile.get()); - pagFile->_stretchedFrameDuration = pagLayer->layer->duration; - pagFile->_timeStretchMode = file->timeStretchMode; - return pagFile; + if (file == nullptr) { + return nullptr; + } + auto pagLayer = BuildPAGLayer(file, file->getRootLayer()); + auto locker = std::make_shared(); + pagLayer->updateRootLocker(locker); + if (pagLayer->layerType() != LayerType::PreCompose) { + return nullptr; + } + pagLayer->gotoTime(0); + auto pagFile = std::static_pointer_cast(pagLayer); + pagFile->onAddToRootFile(pagFile.get()); + pagFile->_stretchedFrameDuration = pagLayer->layer->duration; + pagFile->_timeStretchMode = file->timeStretchMode; + return pagFile; } std::shared_ptr PAGFile::BuildPAGLayer(std::shared_ptr file, Layer* layer) { - PAGLayer* pagLayer; - switch (layer->type()) { + PAGLayer* pagLayer; + switch (layer->type()) { case LayerType::Solid: { - pagLayer = new PAGSolidLayer(file, static_cast(layer)); - } break; + pagLayer = new PAGSolidLayer(file, static_cast(layer)); + } + break; case LayerType::Text: { - pagLayer = new PAGTextLayer(file, static_cast(layer)); - pagLayer->_editableIndex = file->getEditableIndex(static_cast(layer)); - } break; + pagLayer = new PAGTextLayer(file, static_cast(layer)); + pagLayer->_editableIndex = file->getEditableIndex(static_cast(layer)); + } + break; case LayerType::Shape: { - pagLayer = new PAGShapeLayer(file, static_cast(layer)); - } break; + pagLayer = new PAGShapeLayer(file, static_cast(layer)); + } + break; case LayerType::Image: { - pagLayer = new PAGImageLayer(file, static_cast(layer)); - pagLayer->_editableIndex = file->getEditableIndex(static_cast(layer)); - } break; + pagLayer = new PAGImageLayer(file, static_cast(layer)); + pagLayer->_editableIndex = file->getEditableIndex(static_cast(layer)); + } + break; case LayerType::PreCompose: { - if (layer == file->getRootLayer()) { - pagLayer = new PAGFile(file, static_cast(layer)); - } else { - pagLayer = new PAGComposition(file, static_cast(layer)); - } - - auto composition = static_cast(layer)->composition; - if (composition->type() == CompositionType::Vector) { - auto& layers = static_cast(composition)->layers; - // The index order of PAGLayers is different from Layers in File. - for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { - auto childLayer = layers[i]; - auto childPAGLayer = BuildPAGLayer(file, childLayer); - static_cast(pagLayer)->layers.push_back(childPAGLayer); - childPAGLayer->_parent = static_cast(pagLayer); - if (childLayer->trackMatteLayer) { - childPAGLayer->_trackMatteLayer = BuildPAGLayer(file, childLayer->trackMatteLayer); - childPAGLayer->_trackMatteLayer->trackMatteOwner = childPAGLayer.get(); - } + if (layer == file->getRootLayer()) { + pagLayer = new PAGFile(file, static_cast(layer)); + } else { + pagLayer = new PAGComposition(file, static_cast(layer)); } - } - } break; + + auto composition = static_cast(layer)->composition; + if (composition->type() == CompositionType::Vector) { + auto& layers = static_cast(composition)->layers; + // The index order of PAGLayers is different from Layers in File. + for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { + auto childLayer = layers[i]; + auto childPAGLayer = BuildPAGLayer(file, childLayer); + static_cast(pagLayer)->layers.push_back(childPAGLayer); + childPAGLayer->_parent = static_cast(pagLayer); + if (childLayer->trackMatteLayer) { + childPAGLayer->_trackMatteLayer = BuildPAGLayer(file, childLayer->trackMatteLayer); + childPAGLayer->_trackMatteLayer->trackMatteOwner = childPAGLayer.get(); + } + } + } + } + break; default: - pagLayer = new PAGLayer(file, layer); - break; - } - auto shared = std::shared_ptr(pagLayer); - pagLayer->weakThis = shared; - return shared; + pagLayer = new PAGLayer(file, layer); + break; + } + auto shared = std::shared_ptr(pagLayer); + pagLayer->weakThis = shared; + return shared; } PAGFile::PAGFile(std::shared_ptr file, pag::PreComposeLayer* layer) : PAGComposition(file, layer) { - imageHolder = std::make_shared(); + imageHolder = std::make_shared(); } uint16_t PAGFile::tagLevel() { - return file->tagLevel(); + return file->tagLevel(); } int PAGFile::numTexts() { - return file->numTexts(); + return file->numTexts(); } int PAGFile::numImages() { - return file->numImages(); + return file->numImages(); } int PAGFile::numVideos() { - return file->numVideos(); + return file->numVideos(); } std::string PAGFile::path() const { - return file->path; + return file->path; } std::shared_ptr PAGFile::getTextData(int editableTextIndex) { - return file->getTextData(editableTextIndex); + return file->getTextData(editableTextIndex); } void PAGFile::replaceText(int editableTextIndex, std::shared_ptr textData) { - LockGuard autoLock(rootLocker); - auto textLayers = getLayersByEditableIndexInternal(editableTextIndex, LayerType::Text); - for (auto& pagLayer : textLayers) { - auto pagTextLayer = std::static_pointer_cast(pagLayer); - pagTextLayer->replaceTextInternal(textData); - } + LockGuard autoLock(rootLocker); + auto textLayers = getLayersByEditableIndexInternal(editableTextIndex, LayerType::Text); + for (auto& pagLayer : textLayers) { + auto pagTextLayer = std::static_pointer_cast(pagLayer); + pagTextLayer->replaceTextInternal(textData); + } } void PAGFile::replaceImage(int editableImageIndex, std::shared_ptr image) { - LockGuard autoLock(rootLocker); - auto imageLayers = getLayersByEditableIndexInternal(editableImageIndex, LayerType::Image); - if (!imageLayers.empty()) { - std::static_pointer_cast(imageLayers[0])->replaceImageInternal(image); - } + LockGuard autoLock(rootLocker); + auto imageLayers = getLayersByEditableIndexInternal(editableImageIndex, LayerType::Image); + if (!imageLayers.empty()) { + std::static_pointer_cast(imageLayers[0])->replaceImageInternal(image); + } } std::vector> PAGFile::getLayersByEditableIndex(int editableIndex, - LayerType layerType) { - LockGuard autoLock(rootLocker); - return getLayersByEditableIndexInternal(editableIndex, layerType); +LayerType layerType) { + LockGuard autoLock(rootLocker); + return getLayersByEditableIndexInternal(editableIndex, layerType); } std::vector> PAGFile::getLayersByEditableIndexInternal( - int editableIndex, LayerType layerType) { - std::vector> result = getLayersBy([=](PAGLayer* pagLayer) -> bool { - return pagLayer->layerType() == layerType && pagLayer->_editableIndex == editableIndex && - pagLayer->file == file; - }); - return result; +int editableIndex, LayerType layerType) { + std::vector> result = getLayersBy([=](PAGLayer* pagLayer) -> bool { + return pagLayer->layerType() == layerType && pagLayer->_editableIndex == editableIndex && + pagLayer->file == file; + }); + return result; } Enum PAGFile::timeStretchMode() const { - LockGuard autoLock(rootLocker); - return _timeStretchMode; + LockGuard autoLock(rootLocker); + return _timeStretchMode; } void PAGFile::setTimeStretchMode(Enum value) { - LockGuard autoLock(rootLocker); - _timeStretchMode = value; + LockGuard autoLock(rootLocker); + _timeStretchMode = value; } void PAGFile::setDuration(int64_t duration) { - LockGuard autoLock(rootLocker); - setDurationInternal(duration); + LockGuard autoLock(rootLocker); + setDurationInternal(duration); } void PAGFile::setDurationInternal(int64_t duration) { - auto totalFrames = TimeToFrame(duration, frameRateInternal()); - if (totalFrames <= 0) { - totalFrames = layer->duration; - } - if (_stretchedFrameDuration == totalFrames) { - return; - } - _stretchedFrameDuration = totalFrames; - if (_parent && _parent->emptyComposition) { - _parent->updateDurationAndFrameRate(); - } - onTimelineChanged(); - notifyModified(); + auto totalFrames = TimeToFrame(duration, frameRateInternal()); + if (totalFrames <= 0) { + totalFrames = layer->duration; + } + if (_stretchedFrameDuration == totalFrames) { + return; + } + _stretchedFrameDuration = totalFrames; + if (_parent && _parent->emptyComposition) { + _parent->updateDurationAndFrameRate(); + } + onTimelineChanged(); + notifyModified(); } std::shared_ptr PAGFile::replaceImageTemporarily(int editableIndex, - std::shared_ptr image) { - if (!imageHolder) { - return nullptr; - } - auto oldImage = imageHolder->getImage(editableIndex); - imageHolder->setImage(editableIndex, image); - notifyModified(true); - return oldImage; + std::shared_ptr image) { + if (!imageHolder) { + return nullptr; + } + auto oldImage = imageHolder->getImage(editableIndex); + imageHolder->setImage(editableIndex, image); + notifyModified(true); + return oldImage; } std::shared_ptr PAGFile::copyOriginal() { - return MakeFrom(file); + return MakeFrom(file); } bool PAGFile::isPAGFile() const { - return true; + return true; } Frame PAGFile::stretchedFrameDuration() const { - return _stretchedFrameDuration; + return _stretchedFrameDuration; } Frame PAGFile::stretchedContentFrame() const { - return _stretchedContentFrame; + return _stretchedContentFrame; } bool PAGFile::gotoTime(int64_t layerTime) { - _stretchedContentFrame = TimeToFrame(layerTime, frameRateInternal()) - startFrame; - if (_stretchedFrameDuration == layer->duration) { - return PAGComposition::gotoTime(layerTime); - } - auto fileTime = stretchedTimeToFileTime(layerTime); - return PAGComposition::gotoTime(fileTime); + _stretchedContentFrame = TimeToFrame(layerTime, frameRateInternal()) - startFrame; + if (_stretchedFrameDuration == layer->duration) { + return PAGComposition::gotoTime(layerTime); + } + auto fileTime = stretchedTimeToFileTime(layerTime); + return PAGComposition::gotoTime(fileTime); } Frame PAGFile::childFrameToLocal(pag::Frame childFrame, float childFrameRate) const { - childFrame = PAGComposition::childFrameToLocal(childFrame, childFrameRate); - if (_stretchedFrameDuration != layer->duration) { - childFrame = fileFrameToStretchedFrame(childFrame); - } - return childFrame; + childFrame = PAGComposition::childFrameToLocal(childFrame, childFrameRate); + if (_stretchedFrameDuration != layer->duration) { + childFrame = fileFrameToStretchedFrame(childFrame); + } + return childFrame; } Frame PAGFile::localFrameToChild(pag::Frame localFrame, float childFrameRate) const { - if (_stretchedFrameDuration != layer->duration) { - localFrame = stretchedFrameToFileFrame(localFrame); - } - return PAGComposition::localFrameToChild(localFrame, childFrameRate); + if (_stretchedFrameDuration != layer->duration) { + localFrame = stretchedFrameToFileFrame(localFrame); + } + return PAGComposition::localFrameToChild(localFrame, childFrameRate); } static void HandleTimeStretch_Repeat(int64_t* fileContent, int64_t layerDuration) { - if (*fileContent >= layerDuration) { - *fileContent = *fileContent % layerDuration; - } + if (*fileContent >= layerDuration) { + *fileContent = *fileContent % layerDuration; + } } static void HandleTimeStretch_RepeatInverted(int64_t* fileContent, int64_t layerDuration) { - if (*fileContent >= layerDuration) { - auto count = static_cast(ceil(static_cast(*fileContent + 1) / layerDuration)); - *fileContent = *fileContent % layerDuration; - if (count % 2 == 0) { - *fileContent = layerDuration - 1 - *fileContent; + if (*fileContent >= layerDuration) { + auto count = static_cast(ceil(static_cast(*fileContent + 1) / layerDuration)); + *fileContent = *fileContent % layerDuration; + if (count % 2 == 0) { + *fileContent = layerDuration - 1 - *fileContent; + } } - } } Frame PAGFile::stretchedFrameToFileFrame(Frame stretchedFrame) const { - auto fileContentFrame = stretchedFrame - startFrame; - if (fileContentFrame <= 0) { - return stretchedFrame; - } - auto layerDuration = frameDuration(); - if (fileContentFrame >= _stretchedFrameDuration) { - return stretchedFrame - _stretchedContentFrame + layerDuration; - } - - switch (_timeStretchMode) { + auto fileContentFrame = stretchedFrame - startFrame; + if (fileContentFrame <= 0) { + return stretchedFrame; + } + auto layerDuration = frameDuration(); + if (fileContentFrame >= _stretchedFrameDuration) { + return stretchedFrame - _stretchedContentFrame + layerDuration; + } + + switch (_timeStretchMode) { case PAGTimeStretchMode::Scale: { - if (file->hasScaledTimeRange()) { - fileContentFrame = scaledFrameToFileFrame(fileContentFrame, file->scaledTimeRange); - } else { - auto progress = FrameToProgress(fileContentFrame, _stretchedFrameDuration); - fileContentFrame = ProgressToFrame(progress, layerDuration); - } - } break; + if (file->hasScaledTimeRange()) { + fileContentFrame = scaledFrameToFileFrame(fileContentFrame, file->scaledTimeRange); + } else { + auto progress = FrameToProgress(fileContentFrame, _stretchedFrameDuration); + fileContentFrame = ProgressToFrame(progress, layerDuration); + } + } + break; case PAGTimeStretchMode::Repeat: { - HandleTimeStretch_Repeat(&fileContentFrame, layerDuration); - } break; + HandleTimeStretch_Repeat(&fileContentFrame, layerDuration); + } + break; case PAGTimeStretchMode::RepeatInverted: { - HandleTimeStretch_RepeatInverted(&fileContentFrame, layerDuration); - } break; + HandleTimeStretch_RepeatInverted(&fileContentFrame, layerDuration); + } + break; default: { - if (fileContentFrame >= layerDuration) { - fileContentFrame = layerDuration - 1; - } - } break; - } - return startFrame + fileContentFrame; + if (fileContentFrame >= layerDuration) { + fileContentFrame = layerDuration - 1; + } + } + break; + } + return startFrame + fileContentFrame; } int64_t PAGFile::stretchedTimeToFileTime(int64_t stretchedTime) const { - auto fileContentTime = stretchedTime - startTimeInternal(); - if (fileContentTime <= 0) { - return stretchedTime; - } - auto layerDuration = FrameToTime(frameDuration(), frameRateInternal()); - auto stretchedTimeDuration = FrameToTime(_stretchedFrameDuration, frameRateInternal()); - if (fileContentTime >= stretchedTimeDuration) { - return stretchedTime - stretchedTimeDuration + layerDuration; - } - - switch (_timeStretchMode) { + auto fileContentTime = stretchedTime - startTimeInternal(); + if (fileContentTime <= 0) { + return stretchedTime; + } + auto layerDuration = FrameToTime(frameDuration(), frameRateInternal()); + auto stretchedTimeDuration = FrameToTime(_stretchedFrameDuration, frameRateInternal()); + if (fileContentTime >= stretchedTimeDuration) { + return stretchedTime - stretchedTimeDuration + layerDuration; + } + + switch (_timeStretchMode) { case PAGTimeStretchMode::Scale: { - if (file->hasScaledTimeRange()) { - auto fileContentFrame = scaledFrameToFileFrame( - TimeToFrame(fileContentTime, frameRateInternal()), file->scaledTimeRange); - fileContentTime = FrameToTime(fileContentFrame, frameRateInternal()); - } else { - auto progress = TimeToProgress(fileContentTime, stretchedTimeDuration); - fileContentTime = ProgressToTime(progress, layerDuration); - } - } break; + if (file->hasScaledTimeRange()) { + auto fileContentFrame = scaledFrameToFileFrame( + TimeToFrame(fileContentTime, frameRateInternal()), file->scaledTimeRange); + fileContentTime = FrameToTime(fileContentFrame, frameRateInternal()); + } else { + auto progress = TimeToProgress(fileContentTime, stretchedTimeDuration); + fileContentTime = ProgressToTime(progress, layerDuration); + } + } + break; case PAGTimeStretchMode::Repeat: { - HandleTimeStretch_Repeat(&fileContentTime, layerDuration); - } break; + HandleTimeStretch_Repeat(&fileContentTime, layerDuration); + } + break; case PAGTimeStretchMode::RepeatInverted: { - HandleTimeStretch_RepeatInverted(&fileContentTime, layerDuration); - } break; + HandleTimeStretch_RepeatInverted(&fileContentTime, layerDuration); + } + break; default: { - if (fileContentTime >= layerDuration) { - fileContentTime = layerDuration - 1; - } - } break; - } - return startTimeInternal() + fileContentTime; + if (fileContentTime >= layerDuration) { + fileContentTime = layerDuration - 1; + } + } + break; + } + return startTimeInternal() + fileContentTime; } Frame PAGFile::scaledFrameToFileFrame(Frame scaledFrame, const TimeRange& scaledTimeRange) const { - if (scaledFrame < scaledTimeRange.start) { - return scaledFrame; - } - auto layerDuration = frameDuration(); - auto minDuration = scaledTimeRange.start + layerDuration - scaledTimeRange.end; - if (_stretchedFrameDuration <= minDuration) { - return scaledFrame + scaledTimeRange.end - scaledTimeRange.start; - } - auto offsetFrame = _stretchedFrameDuration - layerDuration; - if (scaledFrame >= scaledTimeRange.end + offsetFrame) { - return scaledFrame - offsetFrame; - } - auto progress = (scaledFrame * 1.0 - scaledTimeRange.start) / - static_cast(_stretchedFrameDuration - minDuration - 1); - auto targetFrame = - static_cast(round(progress * static_cast(layerDuration - minDuration - 1))); - return targetFrame + scaledTimeRange.start; + if (scaledFrame < scaledTimeRange.start) { + return scaledFrame; + } + auto layerDuration = frameDuration(); + auto minDuration = scaledTimeRange.start + layerDuration - scaledTimeRange.end; + if (_stretchedFrameDuration <= minDuration) { + return scaledFrame + scaledTimeRange.end - scaledTimeRange.start; + } + auto offsetFrame = _stretchedFrameDuration - layerDuration; + if (scaledFrame >= scaledTimeRange.end + offsetFrame) { + return scaledFrame - offsetFrame; + } + auto progress = (scaledFrame * 1.0 - scaledTimeRange.start) / + static_cast(_stretchedFrameDuration - minDuration - 1); + auto targetFrame = + static_cast(round(progress * static_cast(layerDuration - minDuration - 1))); + return targetFrame + scaledTimeRange.start; } Frame PAGFile::fileFrameToStretchedFrame(Frame fileFrame) const { - auto stretchedContentFrame = fileFrame - startFrame; - if (stretchedContentFrame <= 0) { - return fileFrame; - } - auto layerDuration = frameDuration(); - if (stretchedContentFrame >= layerDuration) { - return fileFrame + _stretchedFrameDuration - layerDuration; - } - if (_timeStretchMode == PAGTimeStretchMode::Scale) { - if (file->hasScaledTimeRange()) { - stretchedContentFrame = fileFrameToScaledFrame(stretchedContentFrame, file->scaledTimeRange); - } else { - auto progress = FrameToProgress(stretchedContentFrame, layerDuration); - stretchedContentFrame = ProgressToFrame(progress, _stretchedFrameDuration); - } - } - return startFrame + stretchedContentFrame; + auto stretchedContentFrame = fileFrame - startFrame; + if (stretchedContentFrame <= 0) { + return fileFrame; + } + auto layerDuration = frameDuration(); + if (stretchedContentFrame >= layerDuration) { + return fileFrame + _stretchedFrameDuration - layerDuration; + } + if (_timeStretchMode == PAGTimeStretchMode::Scale) { + if (file->hasScaledTimeRange()) { + stretchedContentFrame = fileFrameToScaledFrame(stretchedContentFrame, file->scaledTimeRange); + } else { + auto progress = FrameToProgress(stretchedContentFrame, layerDuration); + stretchedContentFrame = ProgressToFrame(progress, _stretchedFrameDuration); + } + } + return startFrame + stretchedContentFrame; } Frame PAGFile::fileFrameToScaledFrame(Frame fileFrame, const TimeRange& scaledTimeRange) const { - if (fileFrame < scaledTimeRange.start) { - return fileFrame; - } - auto layerDuration = frameDuration(); - auto minDuration = scaledTimeRange.start + layerDuration - scaledTimeRange.end; - if (_stretchedFrameDuration <= minDuration) { - return fileFrame - scaledTimeRange.end + scaledTimeRange.start; - } - if (fileFrame >= scaledTimeRange.end) { - return fileFrame + _stretchedFrameDuration - layerDuration; - } - auto progress = FrameToProgress(fileFrame - scaledTimeRange.start, - scaledTimeRange.end - scaledTimeRange.start); - auto targetFrame = ProgressToFrame(progress, _stretchedFrameDuration - minDuration); - return targetFrame + scaledTimeRange.start; + if (fileFrame < scaledTimeRange.start) { + return fileFrame; + } + auto layerDuration = frameDuration(); + auto minDuration = scaledTimeRange.start + layerDuration - scaledTimeRange.end; + if (_stretchedFrameDuration <= minDuration) { + return fileFrame - scaledTimeRange.end + scaledTimeRange.start; + } + if (fileFrame >= scaledTimeRange.end) { + return fileFrame + _stretchedFrameDuration - layerDuration; + } + auto progress = FrameToProgress(fileFrame - scaledTimeRange.start, + scaledTimeRange.end - scaledTimeRange.start); + auto targetFrame = ProgressToFrame(progress, _stretchedFrameDuration - minDuration); + return targetFrame + scaledTimeRange.start; } } // namespace pag diff --git a/src/rendering/PAGFont.cpp b/src/rendering/PAGFont.cpp index 15b5aa1347..7dcfbb8f99 100644 --- a/src/rendering/PAGFont.cpp +++ b/src/rendering/PAGFont.cpp @@ -22,24 +22,24 @@ namespace pag { PAGFont PAGFont::RegisterFont(const std::string& fontPath, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - return FontManager::RegisterFont(fontPath, ttcIndex, fontFamily, fontStyle); + return FontManager::RegisterFont(fontPath, ttcIndex, fontFamily, fontStyle); } PAGFont PAGFont::RegisterFont(const void* data, size_t length, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - return FontManager::RegisterFont(data, length, ttcIndex, fontFamily, fontStyle); + return FontManager::RegisterFont(data, length, ttcIndex, fontFamily, fontStyle); } void PAGFont::UnregisterFont(const PAGFont& font) { - return FontManager::UnregisterFont(font); + return FontManager::UnregisterFont(font); } void PAGFont::SetFallbackFontNames(const std::vector& fontNames) { - FontManager::SetFallbackFontNames(fontNames); + FontManager::SetFallbackFontNames(fontNames); } void PAGFont::SetFallbackFontPaths(const std::vector& fontPaths, const std::vector& ttcIndices) { - FontManager::SetFallbackFontPaths(fontPaths, ttcIndices); + FontManager::SetFallbackFontPaths(fontPaths, ttcIndices); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/PAGPlayer.cpp b/src/rendering/PAGPlayer.cpp index 75f288d9d7..4ff77ebebe 100644 --- a/src/rendering/PAGPlayer.cpp +++ b/src/rendering/PAGPlayer.cpp @@ -29,381 +29,381 @@ namespace pag { PAGPlayer::PAGPlayer() { - stage = PAGStage::Make(0, 0); - rootLocker = stage->rootLocker; - renderCache = new RenderCache(stage.get()); + stage = PAGStage::Make(0, 0); + rootLocker = stage->rootLocker; + renderCache = new RenderCache(stage.get()); } PAGPlayer::~PAGPlayer() { - delete renderCache; - setSurface(nullptr); - stage->removeAllLayers(); - delete reporter; + delete renderCache; + setSurface(nullptr); + stage->removeAllLayers(); + delete reporter; } std::shared_ptr PAGPlayer::getComposition() { - LockGuard autoLock(rootLocker); - return stage->getRootComposition(); + LockGuard autoLock(rootLocker); + return stage->getRootComposition(); } void PAGPlayer::setComposition(std::shared_ptr newComposition) { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - if (pagComposition == newComposition) { - return; - } - if (pagComposition) { - auto index = stage->getLayerIndexInternal(pagComposition); - if (index >= 0) { - stage->doRemoveLayer(index); + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + if (pagComposition == newComposition) { + return; + } + if (pagComposition) { + auto index = stage->getLayerIndexInternal(pagComposition); + if (index >= 0) { + stage->doRemoveLayer(index); + } + delete reporter; + reporter = nullptr; + } + pagComposition = newComposition; + if (pagComposition) { + stage->doAddLayer(pagComposition, 0); + reporter = FileReporter::Make(pagComposition).release(); + updateScaleModeIfNeed(); } - delete reporter; - reporter = nullptr; - } - pagComposition = newComposition; - if (pagComposition) { - stage->doAddLayer(pagComposition, 0); - reporter = FileReporter::Make(pagComposition).release(); - updateScaleModeIfNeed(); - } } std::shared_ptr PAGPlayer::getSurface() { - LockGuard autoLock(rootLocker); - return pagSurface; + LockGuard autoLock(rootLocker); + return pagSurface; } void PAGPlayer::setSurface(std::shared_ptr newSurface) { - auto locker = newSurface ? newSurface->rootLocker : nullptr; - ScopedLock autoLock(rootLocker, locker); - setSurfaceInternal(newSurface); + auto locker = newSurface ? newSurface->rootLocker : nullptr; + ScopedLock autoLock(rootLocker, locker); + setSurfaceInternal(newSurface); } void PAGPlayer::setSurfaceInternal(std::shared_ptr newSurface) { - if (pagSurface == newSurface) { - return; - } - if (newSurface && newSurface->pagPlayer != nullptr) { - LOGE("PAGPlayer.setSurface(): The new surface is already set to another PAGPlayer!"); - return; - } - if (pagSurface) { - pagSurface->pagPlayer = nullptr; - pagSurface->rootLocker = std::make_shared(); - } - pagSurface = newSurface; - if (pagSurface) { - pagSurface->pagPlayer = this; - pagSurface->contentVersion = 0; - pagSurface->rootLocker = rootLocker; - updateStageSize(); - } else { - stage->setContentSizeInternal(0, 0); - } + if (pagSurface == newSurface) { + return; + } + if (newSurface && newSurface->pagPlayer != nullptr) { + LOGE("PAGPlayer.setSurface(): The new surface is already set to another PAGPlayer!"); + return; + } + if (pagSurface) { + pagSurface->pagPlayer = nullptr; + pagSurface->rootLocker = std::make_shared(); + } + pagSurface = newSurface; + if (pagSurface) { + pagSurface->pagPlayer = this; + pagSurface->contentVersion = 0; + pagSurface->rootLocker = rootLocker; + updateStageSize(); + } else { + stage->setContentSizeInternal(0, 0); + } } bool PAGPlayer::videoEnabled() { - LockGuard autoLock(rootLocker); - return renderCache->videoEnabled(); + LockGuard autoLock(rootLocker); + return renderCache->videoEnabled(); } void PAGPlayer::setVideoEnabled(bool value) { - LockGuard autoLock(rootLocker); - renderCache->setVideoEnabled(value); + LockGuard autoLock(rootLocker); + renderCache->setVideoEnabled(value); } bool PAGPlayer::cacheEnabled() { - LockGuard autoLock(rootLocker); - return renderCache->snapshotEnabled(); + LockGuard autoLock(rootLocker); + return renderCache->snapshotEnabled(); } void PAGPlayer::setCacheEnabled(bool value) { - LockGuard autoLock(rootLocker); - renderCache->setSnapshotEnabled(value); + LockGuard autoLock(rootLocker); + renderCache->setSnapshotEnabled(value); } float PAGPlayer::cacheScale() { - LockGuard autoLock(rootLocker); - return stage->cacheScale(); + LockGuard autoLock(rootLocker); + return stage->cacheScale(); } void PAGPlayer::setCacheScale(float value) { - LockGuard autoLock(rootLocker); - stage->setCacheScale(value); + LockGuard autoLock(rootLocker); + stage->setCacheScale(value); } float PAGPlayer::maxFrameRate() { - LockGuard autoLock(rootLocker); - return _maxFrameRate; + LockGuard autoLock(rootLocker); + return _maxFrameRate; } void PAGPlayer::setMaxFrameRate(float value) { - LockGuard autoLock(rootLocker); - if (_maxFrameRate == value) { - return; - } - _maxFrameRate = value; + LockGuard autoLock(rootLocker); + if (_maxFrameRate == value) { + return; + } + _maxFrameRate = value; } int PAGPlayer::scaleMode() { - LockGuard autoLock(rootLocker); - return _scaleMode; + LockGuard autoLock(rootLocker); + return _scaleMode; } void PAGPlayer::setScaleMode(int mode) { - LockGuard autoLock(rootLocker); - _scaleMode = mode; - auto pagComposition = stage->getRootComposition(); - if (_scaleMode == PAGScaleMode::None && pagComposition) { - pagComposition->setMatrixInternal(Matrix::I()); - } - updateScaleModeIfNeed(); + LockGuard autoLock(rootLocker); + _scaleMode = mode; + auto pagComposition = stage->getRootComposition(); + if (_scaleMode == PAGScaleMode::None && pagComposition) { + pagComposition->setMatrixInternal(Matrix::I()); + } + updateScaleModeIfNeed(); } Matrix PAGPlayer::matrix() { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - return pagComposition ? pagComposition->layerMatrix : Matrix::I(); + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + return pagComposition ? pagComposition->layerMatrix : Matrix::I(); } void PAGPlayer::setMatrix(const Matrix& matrix) { - LockGuard autoLock(rootLocker); - _scaleMode = PAGScaleMode::None; - auto pagComposition = stage->getRootComposition(); - if (pagComposition) { - pagComposition->setMatrixInternal(matrix); - } + LockGuard autoLock(rootLocker); + _scaleMode = PAGScaleMode::None; + auto pagComposition = stage->getRootComposition(); + if (pagComposition) { + pagComposition->setMatrixInternal(matrix); + } } int64_t PAGPlayer::duration() { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - return pagComposition ? pagComposition->durationInternal() : 0; + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + return pagComposition ? pagComposition->durationInternal() : 0; } void PAGPlayer::nextFrame() { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - if (pagComposition) { - pagComposition->nextFrameInternal(); - } + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + if (pagComposition) { + pagComposition->nextFrameInternal(); + } } void PAGPlayer::preFrame() { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - if (pagComposition) { - pagComposition->preFrameInternal(); - } + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + if (pagComposition) { + pagComposition->preFrameInternal(); + } } double PAGPlayer::getProgress() { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - return pagComposition ? pagComposition->getProgressInternal() : 0; + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + return pagComposition ? pagComposition->getProgressInternal() : 0; } void PAGPlayer::setProgress(double percent) { - LockGuard autoLock(rootLocker); - auto pagComposition = stage->getRootComposition(); - if (pagComposition == nullptr) { - return; - } - auto realProgress = percent; - auto frameRate = pagComposition->frameRateInternal(); - if (_maxFrameRate < frameRate && _maxFrameRate > 0) { - auto duration = pagComposition->durationInternal(); - auto totalFrames = TimeToFrame(duration, frameRate); - auto numFrames = ceilf(totalFrames * _maxFrameRate / frameRate); - // 首先计算在maxFrameRate的帧号,之后重新计算progress - auto targetFrame = ProgressToFrame(realProgress, numFrames); - realProgress = FrameToProgress(targetFrame, numFrames); - } - pagComposition->setProgressInternal(realProgress); + LockGuard autoLock(rootLocker); + auto pagComposition = stage->getRootComposition(); + if (pagComposition == nullptr) { + return; + } + auto realProgress = percent; + auto frameRate = pagComposition->frameRateInternal(); + if (_maxFrameRate < frameRate && _maxFrameRate > 0) { + auto duration = pagComposition->durationInternal(); + auto totalFrames = TimeToFrame(duration, frameRate); + auto numFrames = ceilf(totalFrames * _maxFrameRate / frameRate); + // 首先计算在maxFrameRate的帧号,之后重新计算progress + auto targetFrame = ProgressToFrame(realProgress, numFrames); + realProgress = FrameToProgress(targetFrame, numFrames); + } + pagComposition->setProgressInternal(realProgress); } bool PAGPlayer::autoClear() { - LockGuard autoLock(rootLocker); - return _autoClear; + LockGuard autoLock(rootLocker); + return _autoClear; } void PAGPlayer::setAutoClear(bool value) { - LockGuard autoLock(rootLocker); - if (_autoClear == value) { - return; - } - _autoClear = value; - stage->notifyModified(true); + LockGuard autoLock(rootLocker); + if (_autoClear == value) { + return; + } + _autoClear = value; + stage->notifyModified(true); } bool PAGPlayer::wait(const BackendSemaphore& waitSemaphore) { - LockGuard autoLock(rootLocker); - if (pagSurface == nullptr) { - return false; - } - return pagSurface->wait(waitSemaphore); + LockGuard autoLock(rootLocker); + if (pagSurface == nullptr) { + return false; + } + return pagSurface->wait(waitSemaphore); } bool PAGPlayer::flushAndSignalSemaphore(BackendSemaphore* signalSemaphore) { - LockGuard autoLock(rootLocker); - return flushInternal(signalSemaphore); + LockGuard autoLock(rootLocker); + return flushInternal(signalSemaphore); } bool PAGPlayer::flush() { - LockGuard autoLock(rootLocker); - return flushInternal(nullptr); + LockGuard autoLock(rootLocker); + return flushInternal(nullptr); } bool PAGPlayer::flushInternal(BackendSemaphore* signalSemaphore) { - if (pagSurface == nullptr) { - return false; - } - updateStageSize(); + if (pagSurface == nullptr) { + return false; + } + updateStageSize(); #ifndef PAG_BUILD_FOR_WEB - // must be called before content comparing, otherwise decoders can not be prepared. - renderCache->prepareFrame(); + // must be called before content comparing, otherwise decoders can not be prepared. + renderCache->prepareFrame(); #endif - auto renderingStart = GetTimer(); - if (contentVersion != stage->getContentVersion()) { - contentVersion = stage->getContentVersion(); - Recorder recorder = {}; - stage->draw(&recorder); - lastGraphic = recorder.makeGraphic(); - } - auto presentingStart = GetTimer(); - if (lastGraphic) { - lastGraphic->prepare(renderCache); - } - if (!pagSurface->draw(renderCache, lastGraphic, signalSemaphore, _autoClear)) { - return false; - } - auto finishTime = GetTimer(); - renderCache->renderingTime = presentingStart - renderingStart; - renderCache->presentingTime = finishTime - presentingStart; - renderCache->presentingTime -= - renderCache->imageDecodingTime + renderCache->textureUploadingTime + - renderCache->programCompilingTime + renderCache->hardwareDecodingTime + - renderCache->softwareDecodingTime; - renderCache->totalTime = finishTime - renderingStart; - // auto composition = stage->getRootComposition(); - // if (composition) { - // renderCache->printPerformance(composition->currentFrameInternal()); - // } - if (reporter) { - reporter->recordPerformance(renderCache); - } - return true; + auto renderingStart = GetTimer(); + if (contentVersion != stage->getContentVersion()) { + contentVersion = stage->getContentVersion(); + Recorder recorder = {}; + stage->draw(&recorder); + lastGraphic = recorder.makeGraphic(); + } + auto presentingStart = GetTimer(); + if (lastGraphic) { + lastGraphic->prepare(renderCache); + } + if (!pagSurface->draw(renderCache, lastGraphic, signalSemaphore, _autoClear)) { + return false; + } + auto finishTime = GetTimer(); + renderCache->renderingTime = presentingStart - renderingStart; + renderCache->presentingTime = finishTime - presentingStart; + renderCache->presentingTime -= + renderCache->imageDecodingTime + renderCache->textureUploadingTime + + renderCache->programCompilingTime + renderCache->hardwareDecodingTime + + renderCache->softwareDecodingTime; + renderCache->totalTime = finishTime - renderingStart; + // auto composition = stage->getRootComposition(); + // if (composition) { + // renderCache->printPerformance(composition->currentFrameInternal()); + // } + if (reporter) { + reporter->recordPerformance(renderCache); + } + return true; } Rect PAGPlayer::getBounds(std::shared_ptr pagLayer) { - if (pagLayer == nullptr) { - return Rect::MakeEmpty(); - } - LockGuard autoLock(rootLocker); - updateStageSize(); - Rect bounds = {}; - pagLayer->measureBounds(&bounds); - auto layer = pagLayer.get(); - bool contains = false; - while (layer) { - if (layer == stage.get()) { - contains = true; - break; + if (pagLayer == nullptr) { + return Rect::MakeEmpty(); } - layer->getTotalMatrixInternal().mapRect(&bounds); - if (layer->_parent == nullptr && layer->trackMatteOwner) { - layer = layer->trackMatteOwner->_parent; - } else { - layer = layer->_parent; + LockGuard autoLock(rootLocker); + updateStageSize(); + Rect bounds = {}; + pagLayer->measureBounds(&bounds); + auto layer = pagLayer.get(); + bool contains = false; + while (layer) { + if (layer == stage.get()) { + contains = true; + break; + } + layer->getTotalMatrixInternal().mapRect(&bounds); + if (layer->_parent == nullptr && layer->trackMatteOwner) { + layer = layer->trackMatteOwner->_parent; + } else { + layer = layer->_parent; + } } - } - return contains ? bounds : Rect::MakeEmpty(); + return contains ? bounds : Rect::MakeEmpty(); } std::vector> PAGPlayer::getLayersUnderPoint(float surfaceX, - float surfaceY) { - LockGuard autoLock(rootLocker); - updateStageSize(); - std::vector> results; - stage->getLayersUnderPointInternal(surfaceX, surfaceY, &results); - return results; +float surfaceY) { + LockGuard autoLock(rootLocker); + updateStageSize(); + std::vector> results; + stage->getLayersUnderPointInternal(surfaceX, surfaceY, &results); + return results; } bool PAGPlayer::hitTestPoint(std::shared_ptr pagLayer, float surfaceX, float surfaceY, bool pixelHitTest) { - LockGuard autoLock(rootLocker); - updateStageSize(); - auto local = pagLayer->globalToLocalPoint(surfaceX, surfaceY); - if (!pixelHitTest) { - Rect bounds = {}; - pagLayer->measureBounds(&bounds); - return bounds.contains(local.x, local.y); - } + LockGuard autoLock(rootLocker); + updateStageSize(); + auto local = pagLayer->globalToLocalPoint(surfaceX, surfaceY); + if (!pixelHitTest) { + Rect bounds = {}; + pagLayer->measureBounds(&bounds); + return bounds.contains(local.x, local.y); + } - if (pagSurface == nullptr || pagLayer->getStage() != stage.get()) { - return false; - } - Recorder recorder = {}; - pagLayer->draw(&recorder); - auto graphic = recorder.makeGraphic(); - return pagSurface->hitTest(renderCache, graphic, local.x, local.y); + if (pagSurface == nullptr || pagLayer->getStage() != stage.get()) { + return false; + } + Recorder recorder = {}; + pagLayer->draw(&recorder); + auto graphic = recorder.makeGraphic(); + return pagSurface->hitTest(renderCache, graphic, local.x, local.y); } int64_t PAGPlayer::getTimeStampInternal() { - auto pagComposition = stage->getRootComposition(); - if (pagComposition == nullptr) { - return 0; - } - auto duration = pagComposition->durationInternal(); - auto progress = pagComposition->getProgressInternal(); - return static_cast(ceil(progress * duration)); + auto pagComposition = stage->getRootComposition(); + if (pagComposition == nullptr) { + return 0; + } + auto duration = pagComposition->durationInternal(); + auto progress = pagComposition->getProgressInternal(); + return static_cast(ceil(progress * duration)); } int64_t PAGPlayer::renderingTime() { - LockGuard autoLock(rootLocker); - // TODO(domrjchen): update the performance monitoring panel of PAGViewer to display the new - // properties - return renderCache->totalTime - renderCache->presentingTime - renderCache->imageDecodingTime; + LockGuard autoLock(rootLocker); + // TODO(domrjchen): update the performance monitoring panel of PAGViewer to display the new + // properties + return renderCache->totalTime - renderCache->presentingTime - renderCache->imageDecodingTime; } int64_t PAGPlayer::imageDecodingTime() { - LockGuard autoLock(rootLocker); - return renderCache->imageDecodingTime; + LockGuard autoLock(rootLocker); + return renderCache->imageDecodingTime; } int64_t PAGPlayer::presentingTime() { - LockGuard autoLock(rootLocker); - return renderCache->presentingTime; + LockGuard autoLock(rootLocker); + return renderCache->presentingTime; } int64_t PAGPlayer::graphicsMemory() { - LockGuard autoLock(rootLocker); - return renderCache->memoryUsage(); + LockGuard autoLock(rootLocker); + return renderCache->memoryUsage(); } void PAGPlayer::updateStageSize() { - if (pagSurface == nullptr) { - return; - } - auto surfaceWidth = pagSurface->drawable->width(); - auto surfaceHeight = pagSurface->drawable->height(); - if (surfaceWidth != stage->widthInternal() || surfaceHeight != stage->heightInternal()) { - stage->setContentSizeInternal(surfaceWidth, surfaceHeight); - updateScaleModeIfNeed(); - } + if (pagSurface == nullptr) { + return; + } + auto surfaceWidth = pagSurface->drawable->width(); + auto surfaceHeight = pagSurface->drawable->height(); + if (surfaceWidth != stage->widthInternal() || surfaceHeight != stage->heightInternal()) { + stage->setContentSizeInternal(surfaceWidth, surfaceHeight); + updateScaleModeIfNeed(); + } } void PAGPlayer::updateScaleModeIfNeed() { - auto pagComposition = stage->getRootComposition(); - if (!pagComposition) { - return; - } - if (stage->widthInternal() > 0 && stage->heightInternal() > 0 && - _scaleMode != PAGScaleMode::None) { - auto matrix = ApplyScaleMode(_scaleMode, pagComposition->widthInternal(), - pagComposition->heightInternal(), stage->widthInternal(), - stage->heightInternal()); - pagComposition->setMatrixInternal(matrix); - } + auto pagComposition = stage->getRootComposition(); + if (!pagComposition) { + return; + } + if (stage->widthInternal() > 0 && stage->heightInternal() > 0 && + _scaleMode != PAGScaleMode::None) { + auto matrix = ApplyScaleMode(_scaleMode, pagComposition->widthInternal(), + pagComposition->heightInternal(), stage->widthInternal(), + stage->heightInternal()); + pagComposition->setMatrixInternal(matrix); + } } } // namespace pag diff --git a/src/rendering/PAGSurface.cpp b/src/rendering/PAGSurface.cpp index c051189219..5d1cd4d6e8 100644 --- a/src/rendering/PAGSurface.cpp +++ b/src/rendering/PAGSurface.cpp @@ -29,215 +29,215 @@ namespace pag { std::shared_ptr PAGSurface::MakeFrom(std::shared_ptr drawable) { - if (drawable == nullptr) { - return nullptr; - } - return std::shared_ptr(new PAGSurface(std::move(drawable))); + if (drawable == nullptr) { + return nullptr; + } + return std::shared_ptr(new PAGSurface(std::move(drawable))); } static std::shared_ptr GetCurrentDevice(bool forAsyncThread) { - if (forAsyncThread) { - auto sharedContext = NativeGLDevice::GetCurrentNativeHandle(); - auto device = NativeGLDevice::Make(sharedContext); - if (device) { - return device; + if (forAsyncThread) { + auto sharedContext = NativeGLDevice::GetCurrentNativeHandle(); + auto device = NativeGLDevice::Make(sharedContext); + if (device) { + return device; + } } - } - return NativeGLDevice::Current(); + return NativeGLDevice::Current(); } std::shared_ptr PAGSurface::MakeFrom(const BackendRenderTarget& renderTarget, - ImageOrigin origin) { - auto device = NativeGLDevice::Current(); - if (device == nullptr || !renderTarget.isValid()) { - return nullptr; - } - auto drawable = std::make_shared(device, renderTarget, origin); - return MakeFrom(std::move(drawable)); + ImageOrigin origin) { + auto device = NativeGLDevice::Current(); + if (device == nullptr || !renderTarget.isValid()) { + return nullptr; + } + auto drawable = std::make_shared(device, renderTarget, origin); + return MakeFrom(std::move(drawable)); } std::shared_ptr PAGSurface::MakeFrom(const BackendTexture& texture, ImageOrigin origin, - bool forAsyncThread) { - auto device = GetCurrentDevice(forAsyncThread); - if (device == nullptr || !texture.isValid()) { - return nullptr; - } - auto drawable = std::make_shared(device, texture, origin); - return MakeFrom(std::move(drawable)); + bool forAsyncThread) { + auto device = GetCurrentDevice(forAsyncThread); + if (device == nullptr || !texture.isValid()) { + return nullptr; + } + auto drawable = std::make_shared(device, texture, origin); + return MakeFrom(std::move(drawable)); } std::shared_ptr PAGSurface::MakeOffscreen(int width, int height) { - auto device = NativeGLDevice::Make(); - if (device == nullptr || width <= 0 || height <= 0) { - return nullptr; - } - auto drawable = std::make_shared(width, height, device); - return std::shared_ptr(new PAGSurface(drawable)); + auto device = NativeGLDevice::Make(); + if (device == nullptr || width <= 0 || height <= 0) { + return nullptr; + } + auto drawable = std::make_shared(width, height, device); + return std::shared_ptr(new PAGSurface(drawable)); } PAGSurface::PAGSurface(std::shared_ptr drawable) : drawable(std::move(drawable)) { - rootLocker = std::make_shared(); + rootLocker = std::make_shared(); } int PAGSurface::width() { - LockGuard autoLock(rootLocker); - return drawable->width(); + LockGuard autoLock(rootLocker); + return drawable->width(); } int PAGSurface::height() { - LockGuard autoLock(rootLocker); - return drawable->height(); + LockGuard autoLock(rootLocker); + return drawable->height(); } void PAGSurface::updateSize() { - LockGuard autoLock(rootLocker); - surface = nullptr; - device = nullptr; - drawable->updateSize(); + LockGuard autoLock(rootLocker); + surface = nullptr; + device = nullptr; + drawable->updateSize(); } void PAGSurface::freeCache() { - LockGuard autoLock(rootLocker); - if (pagPlayer) { - pagPlayer->renderCache->releaseAll(); - } - surface = nullptr; - if (device) { - auto context = device->lockContext(); - if (context) { - context->purgeResourcesNotUsedIn(0); - device->unlock(); + LockGuard autoLock(rootLocker); + if (pagPlayer) { + pagPlayer->renderCache->releaseAll(); } - } - device = nullptr; + surface = nullptr; + if (device) { + auto context = device->lockContext(); + if (context) { + context->purgeResourcesNotUsedIn(0); + device->unlock(); + } + } + device = nullptr; } bool PAGSurface::clearAll() { - LockGuard autoLock(rootLocker); - if (device == nullptr) { - device = drawable->getDevice(); - } - auto context = lockContext(); - if (!context) { - return false; - } - if (surface == nullptr) { - surface = drawable->createSurface(context); - } - if (surface == nullptr) { + LockGuard autoLock(rootLocker); + if (device == nullptr) { + device = drawable->getDevice(); + } + auto context = lockContext(); + if (!context) { + return false; + } + if (surface == nullptr) { + surface = drawable->createSurface(context); + } + if (surface == nullptr) { + unlockContext(); + return false; + } + contentVersion = 0; // 清空画布后 contentVersion 还原为初始值 0. + auto canvas = surface->getCanvas(); + canvas->clear(); + canvas->flush(); + drawable->setTimeStamp(0); + drawable->present(context); unlockContext(); - return false; - } - contentVersion = 0; // 清空画布后 contentVersion 还原为初始值 0. - auto canvas = surface->getCanvas(); - canvas->clear(); - canvas->flush(); - drawable->setTimeStamp(0); - drawable->present(context); - unlockContext(); - return true; + return true; } bool PAGSurface::readPixels(ColorType colorType, AlphaType alphaType, void* dstPixels, size_t dstRowBytes) { - LockGuard autoLock(rootLocker); - auto context = lockContext(); - if (surface == nullptr || !context) { - return false; - } - auto info = - ImageInfo::Make(surface->width(), surface->height(), colorType, alphaType, dstRowBytes); - auto result = surface->readPixels(info, dstPixels); - unlockContext(); - return result; + LockGuard autoLock(rootLocker); + auto context = lockContext(); + if (surface == nullptr || !context) { + return false; + } + auto info = + ImageInfo::Make(surface->width(), surface->height(), colorType, alphaType, dstRowBytes); + auto result = surface->readPixels(info, dstPixels); + unlockContext(); + return result; } bool PAGSurface::draw(RenderCache* cache, std::shared_ptr graphic, BackendSemaphore* signalSemaphore, bool autoClear) { - if (device == nullptr) { - device = drawable->getDevice(); - } - auto context = lockContext(); - if (!context) { - return false; - } - if (surface != nullptr && autoClear && contentVersion == cache->getContentVersion()) { - unlockContext(); - return false; - } - if (surface == nullptr) { - surface = drawable->createSurface(context); - } - if (surface == nullptr) { + if (device == nullptr) { + device = drawable->getDevice(); + } + auto context = lockContext(); + if (!context) { + return false; + } + if (surface != nullptr && autoClear && contentVersion == cache->getContentVersion()) { + unlockContext(); + return false; + } + if (surface == nullptr) { + surface = drawable->createSurface(context); + } + if (surface == nullptr) { + unlockContext(); + return false; + } + contentVersion = cache->getContentVersion(); + cache->attachToContext(context); + auto canvas = surface->getCanvas(); + if (autoClear) { + canvas->clear(); + } + if (graphic) { + graphic->draw(canvas, cache); + } + surface->flush(signalSemaphore); + cache->detachFromContext(); + drawable->setTimeStamp(pagPlayer->getTimeStampInternal()); + drawable->present(context); unlockContext(); - return false; - } - contentVersion = cache->getContentVersion(); - cache->attachToContext(context); - auto canvas = surface->getCanvas(); - if (autoClear) { - canvas->clear(); - } - if (graphic) { - graphic->draw(canvas, cache); - } - surface->flush(signalSemaphore); - cache->detachFromContext(); - drawable->setTimeStamp(pagPlayer->getTimeStampInternal()); - drawable->present(context); - unlockContext(); - return true; + return true; } bool PAGSurface::wait(const BackendSemaphore& waitSemaphore) { - if (!waitSemaphore.isInitialized()) { - return false; - } - if (device == nullptr) { - device = drawable->getDevice(); - } - auto context = lockContext(); - if (!context) { - return false; - } - if (surface == nullptr) { - surface = drawable->createSurface(context); - } - if (surface == nullptr) { + if (!waitSemaphore.isInitialized()) { + return false; + } + if (device == nullptr) { + device = drawable->getDevice(); + } + auto context = lockContext(); + if (!context) { + return false; + } + if (surface == nullptr) { + surface = drawable->createSurface(context); + } + if (surface == nullptr) { + unlockContext(); + return false; + } + auto ret = surface->wait(waitSemaphore); unlockContext(); - return false; - } - auto ret = surface->wait(waitSemaphore); - unlockContext(); - return ret; + return ret; } bool PAGSurface::hitTest(RenderCache* cache, std::shared_ptr graphic, float x, float y) { - if (cache == nullptr || graphic == nullptr) { - return false; - } - auto context = lockContext(); - if (!context) { - return false; - } - cache->attachToContext(context, true); - auto result = graphic->hitTest(cache, x, y); - cache->detachFromContext(); - unlockContext(); - return result; + if (cache == nullptr || graphic == nullptr) { + return false; + } + auto context = lockContext(); + if (!context) { + return false; + } + cache->attachToContext(context, true); + auto result = graphic->hitTest(cache, x, y); + cache->detachFromContext(); + unlockContext(); + return result; } Context* PAGSurface::lockContext() { - if (device == nullptr) { - return nullptr; - } - return device->lockContext(); + if (device == nullptr) { + return nullptr; + } + return device->lockContext(); } void PAGSurface::unlockContext() { - if (device == nullptr) { - return; - } - device->unlock(); + if (device == nullptr) { + return; + } + device->unlock(); } } // namespace pag diff --git a/src/rendering/Performance.cpp b/src/rendering/Performance.cpp index c3fd8dd4b6..70fd15588e 100644 --- a/src/rendering/Performance.cpp +++ b/src/rendering/Performance.cpp @@ -21,36 +21,36 @@ namespace pag { std::string Performance::getPerformanceString() const { - char buffer[300]; - sprintf(buffer, - "%6.1fms[Render] %6.1fms[Image] %6.1fms[Video]" - " %6.1fms[Texture] %6.1fms[Program] %6.1fms[Present] ", - static_cast(renderingTime) / 1000.0, - static_cast(imageDecodingTime) / 1000.0, - static_cast(softwareDecodingTime + hardwareDecodingTime) / 1000.0, - static_cast(textureUploadingTime) / 1000.0, - static_cast(programCompilingTime) / 1000.0, - static_cast(presentingTime) / 1000.0); - return buffer; + char buffer[300]; + sprintf(buffer, + "%6.1fms[Render] %6.1fms[Image] %6.1fms[Video]" + " %6.1fms[Texture] %6.1fms[Program] %6.1fms[Present] ", + static_cast(renderingTime) / 1000.0, + static_cast(imageDecodingTime) / 1000.0, + static_cast(softwareDecodingTime + hardwareDecodingTime) / 1000.0, + static_cast(textureUploadingTime) / 1000.0, + static_cast(programCompilingTime) / 1000.0, + static_cast(presentingTime) / 1000.0); + return buffer; } void Performance::printPerformance(Frame currentFrame) const { - auto performance = getPerformanceString(); - LOGI("%4d | %6.1fms :%s", currentFrame, static_cast(totalTime) / 1000.0, - performance.c_str()); + auto performance = getPerformanceString(); + LOGI("%4d | %6.1fms :%s", currentFrame, static_cast(totalTime) / 1000.0, + performance.c_str()); } void Performance::resetPerformance() { - renderingTime = 0; - presentingTime = 0; - imageDecodingTime = 0; - hardwareDecodingTime = 0; - softwareDecodingTime = 0; - textureUploadingTime = 0; - programCompilingTime = 0; + renderingTime = 0; + presentingTime = 0; + imageDecodingTime = 0; + hardwareDecodingTime = 0; + softwareDecodingTime = 0; + textureUploadingTime = 0; + programCompilingTime = 0; - hardwareDecodingInitialTime = 0; - softwareDecodingInitialTime = 0; - totalTime = 0; + hardwareDecodingInitialTime = 0; + softwareDecodingInitialTime = 0; + totalTime = 0; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/Performance.h b/src/rendering/Performance.h index c43adeef2f..0cf7bd2c2c 100644 --- a/src/rendering/Performance.h +++ b/src/rendering/Performance.h @@ -24,30 +24,30 @@ namespace pag { class Performance { - public: - virtual ~Performance() = default; - // ======= total time ========== - int64_t renderingTime = 0; - int64_t presentingTime = 0; - int64_t textureUploadingTime = 0; - int64_t programCompilingTime = 0; - int64_t imageDecodingTime = 0; - int64_t hardwareDecodingTime = 0; - int64_t softwareDecodingTime = 0; - // ======= total time ========== +public: + virtual ~Performance() = default; + // ======= total time ========== + int64_t renderingTime = 0; + int64_t presentingTime = 0; + int64_t textureUploadingTime = 0; + int64_t programCompilingTime = 0; + int64_t imageDecodingTime = 0; + int64_t hardwareDecodingTime = 0; + int64_t softwareDecodingTime = 0; + // ======= total time ========== - int64_t hardwareDecodingInitialTime = 0; - int64_t softwareDecodingInitialTime = 0; - int64_t totalTime = 0; + int64_t hardwareDecodingInitialTime = 0; + int64_t softwareDecodingInitialTime = 0; + int64_t totalTime = 0; - /** - * Returns the formatted string which contains the performance data. - */ - std::string getPerformanceString() const; + /** + * Returns the formatted string which contains the performance data. + */ + std::string getPerformanceString() const; - void printPerformance(Frame currentFrame) const; + void printPerformance(Frame currentFrame) const; - protected: - void resetPerformance(); +protected: + void resetPerformance(); }; } // namespace pag diff --git a/src/rendering/caches/CompositionCache.cpp b/src/rendering/caches/CompositionCache.cpp index ce7f21f117..3a1b368501 100644 --- a/src/rendering/caches/CompositionCache.cpp +++ b/src/rendering/caches/CompositionCache.cpp @@ -22,37 +22,37 @@ namespace pag { CompositionCache* CompositionCache::Get(Composition* composition) { - std::lock_guard autoLock(composition->locker); - if (composition->cache == nullptr) { - composition->cache = new CompositionCache(composition); - } - return static_cast(composition->cache); + std::lock_guard autoLock(composition->locker); + if (composition->cache == nullptr) { + composition->cache = new CompositionCache(composition); + } + return static_cast(composition->cache); } CompositionCache::CompositionCache(Composition* composition) : composition(composition) { } std::shared_ptr CompositionCache::getContent(Frame contentFrame) { - contentFrame = ConvertFrameByStaticTimeRanges(composition->staticTimeRanges, contentFrame); - if (contentFrame >= composition->duration) { - contentFrame = composition->duration - 1; - } - if (contentFrame < 0) { - contentFrame = 0; - } - std::lock_guard autoLock(locker); - auto cache = frames[contentFrame]; - if (cache == nullptr) { - cache = createContent(contentFrame); - frames[contentFrame] = cache; - } - return cache; + contentFrame = ConvertFrameByStaticTimeRanges(composition->staticTimeRanges, contentFrame); + if (contentFrame >= composition->duration) { + contentFrame = composition->duration - 1; + } + if (contentFrame < 0) { + contentFrame = 0; + } + std::lock_guard autoLock(locker); + auto cache = frames[contentFrame]; + if (cache == nullptr) { + cache = createContent(contentFrame); + frames[contentFrame] = cache; + } + return cache; } std::shared_ptr CompositionCache::createContent(Frame compositionFrame) { - if (composition->type() == CompositionType::Vector) { - return RenderVectorComposition(static_cast(composition), compositionFrame); - } - return RenderSequenceComposition(composition, compositionFrame); + if (composition->type() == CompositionType::Vector) { + return RenderVectorComposition(static_cast(composition), compositionFrame); + } + return RenderSequenceComposition(composition, compositionFrame); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/CompositionCache.h b/src/rendering/caches/CompositionCache.h index 9684df879a..036bf545bb 100644 --- a/src/rendering/caches/CompositionCache.h +++ b/src/rendering/caches/CompositionCache.h @@ -24,19 +24,19 @@ namespace pag { class CompositionCache : public Cache { - public: - static CompositionCache* Get(Composition* composition); +public: + static CompositionCache* Get(Composition* composition); - std::shared_ptr getContent(Frame contentFrame); + std::shared_ptr getContent(Frame contentFrame); - protected: - std::shared_ptr createContent(Frame compositionFrame); +protected: + std::shared_ptr createContent(Frame compositionFrame); - private: - std::mutex locker = {}; - Composition* composition = nullptr; - std::unordered_map> frames; +private: + std::mutex locker = {}; + Composition* composition = nullptr; + std::unordered_map> frames; - explicit CompositionCache(Composition* composition); + explicit CompositionCache(Composition* composition); }; } // namespace pag diff --git a/src/rendering/caches/ContentCache.cpp b/src/rendering/caches/ContentCache.cpp index ba5190c356..71d6084b2f 100644 --- a/src/rendering/caches/ContentCache.cpp +++ b/src/rendering/caches/ContentCache.cpp @@ -25,77 +25,77 @@ ContentCache::ContentCache(Layer* layer) } void ContentCache::update() { - staticTimeRanges = {layer->visibleRange()}; - excludeVaryingRanges(&staticTimeRanges); - staticTimeRanges = OffsetTimeRanges(staticTimeRanges, -layer->startTime); - _contentStatic = !HasVaryingTimeRange(&staticTimeRanges, 0, layer->duration); - _hasFilters = (!layer->effects.empty() || !layer->layerStyles.empty() || layer->motionBlur); - // 理论上当图层的matrix带了缩放时也不能缓存,会导致图层样式也会跟着缩放。但目前投影等滤镜的效果看起来区别不明显,性能优化考虑暂时忽略。 - _cacheFilters = _hasFilters && checkCacheFilters(); + staticTimeRanges = {layer->visibleRange()}; + excludeVaryingRanges(&staticTimeRanges); + staticTimeRanges = OffsetTimeRanges(staticTimeRanges, -layer->startTime); + _contentStatic = !HasVaryingTimeRange(&staticTimeRanges, 0, layer->duration); + _hasFilters = (!layer->effects.empty() || !layer->layerStyles.empty() || layer->motionBlur); + // 理论上当图层的matrix带了缩放时也不能缓存,会导致图层样式也会跟着缩放。但目前投影等滤镜的效果看起来区别不明显,性能优化考虑暂时忽略。 + _cacheFilters = _hasFilters && checkCacheFilters(); - if (_cacheFilters) { - _cacheEnabled = true; - } else { - _cacheEnabled = checkCacheEnabled(); - } + if (_cacheFilters) { + _cacheEnabled = true; + } else { + _cacheEnabled = checkCacheEnabled(); + } } bool ContentCache::checkCacheFilters() { - bool varyingLayerStyle = false; - bool varyingEffect = false; - bool processVisibleAreaOnly = true; - if (!layer->layerStyles.empty()) { - std::vector timeRanges = {layer->visibleRange()}; - for (auto& layerStyle : layer->layerStyles) { - layerStyle->excludeVaryingRanges(&timeRanges); + bool varyingLayerStyle = false; + bool varyingEffect = false; + bool processVisibleAreaOnly = true; + if (!layer->layerStyles.empty()) { + std::vector timeRanges = {layer->visibleRange()}; + for (auto& layerStyle : layer->layerStyles) { + layerStyle->excludeVaryingRanges(&timeRanges); + } + timeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); + varyingLayerStyle = HasVaryingTimeRange(&timeRanges, 0, layer->duration); } - timeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); - varyingLayerStyle = HasVaryingTimeRange(&timeRanges, 0, layer->duration); - } - if (!layer->effects.empty()) { - std::vector timeRanges = {layer->visibleRange()}; - for (auto& effect : layer->effects) { - effect->excludeVaryingRanges(&timeRanges); - if (!effect->processVisibleAreaOnly()) { - processVisibleAreaOnly = false; - } + if (!layer->effects.empty()) { + std::vector timeRanges = {layer->visibleRange()}; + for (auto& effect : layer->effects) { + effect->excludeVaryingRanges(&timeRanges); + if (!effect->processVisibleAreaOnly()) { + processVisibleAreaOnly = false; + } + } + timeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); + varyingEffect = HasVaryingTimeRange(&timeRanges, 0, layer->duration); } - timeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); - varyingEffect = HasVaryingTimeRange(&timeRanges, 0, layer->duration); - } - // 理论上当图层的matrix带了缩放时也不能缓存,会导致图层样式也会跟着缩放。但目前投影等滤镜的效果看起来区别不明显,性能优化考虑暂时忽略。 - return layer->masks.empty() && !layer->motionBlur && processVisibleAreaOnly && - !varyingLayerStyle && !varyingEffect; + // 理论上当图层的matrix带了缩放时也不能缓存,会导致图层样式也会跟着缩放。但目前投影等滤镜的效果看起来区别不明显,性能优化考虑暂时忽略。 + return layer->masks.empty() && !layer->motionBlur && processVisibleAreaOnly && + !varyingLayerStyle && !varyingEffect; } bool ContentCache::checkCacheEnabled() { - auto cacheEnabled = false; - if (layer->cachePolicy != CachePolicy::Auto) { - cacheEnabled = layer->cachePolicy == CachePolicy::Enable; - } else if (!layer->effects.empty() || !layer->layerStyles.empty() || layer->motionBlur) { - // 滤镜不缓存到纹理内,但含有滤镜每帧的输入都要求是纹理,开启纹理缓存的性能会更高。 - cacheEnabled = true; - } else { - // PreComposeLayer 和 ImageLayer 在 createContent() 时会创建 - // Image,不需要上层额外判断是否需要缓存。 - if (layer->type() == LayerType::Text || layer->type() == LayerType::Shape) { - auto staticContent = !HasVaryingTimeRange(getStaticTimeRanges(), 0, layer->duration); - cacheEnabled = staticContent && layer->duration > 1; + auto cacheEnabled = false; + if (layer->cachePolicy != CachePolicy::Auto) { + cacheEnabled = layer->cachePolicy == CachePolicy::Enable; + } else if (!layer->effects.empty() || !layer->layerStyles.empty() || layer->motionBlur) { + // 滤镜不缓存到纹理内,但含有滤镜每帧的输入都要求是纹理,开启纹理缓存的性能会更高。 + cacheEnabled = true; + } else { + // PreComposeLayer 和 ImageLayer 在 createContent() 时会创建 + // Image,不需要上层额外判断是否需要缓存。 + if (layer->type() == LayerType::Text || layer->type() == LayerType::Shape) { + auto staticContent = !HasVaryingTimeRange(getStaticTimeRanges(), 0, layer->duration); + cacheEnabled = staticContent && layer->duration > 1; + } } - } - return cacheEnabled; + return cacheEnabled; } Content* ContentCache::createCache(Frame layerFrame) { - auto content = createContent(layerFrame); - if (_cacheFilters) { - auto filterModifier = FilterModifier::Make(layer, layerFrame); - content->graphic = Graphic::MakeCompose(content->graphic, filterModifier); - } - if (_cacheEnabled) { - content->graphic = Picture::MakeFrom(getCacheID(), content->graphic); - } - return content; + auto content = createContent(layerFrame); + if (_cacheFilters) { + auto filterModifier = FilterModifier::Make(layer, layerFrame); + content->graphic = Graphic::MakeCompose(content->graphic, filterModifier); + } + if (_cacheEnabled) { + content->graphic = Picture::MakeFrom(getCacheID(), content->graphic); + } + return content; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/ContentCache.h b/src/rendering/caches/ContentCache.h index 42a63f7ea6..e4c048f2bc 100644 --- a/src/rendering/caches/ContentCache.h +++ b/src/rendering/caches/ContentCache.h @@ -24,58 +24,58 @@ namespace pag { class ContentCache : public FrameCache { - public: - explicit ContentCache(Layer* layer); +public: + explicit ContentCache(Layer* layer); - bool cacheEnabled() const { - return _cacheEnabled; - } + bool cacheEnabled() const { + return _cacheEnabled; + } - bool hasFilters() const { - return _hasFilters; - } + bool hasFilters() const { + return _hasFilters; + } - bool cacheFilters() const { - return _cacheFilters; - } + bool cacheFilters() const { + return _cacheFilters; + } - bool contentStatic() const { - return _contentStatic; - } + bool contentStatic() const { + return _contentStatic; + } - void update(); + void update(); - protected: - Layer* layer = nullptr; - bool _cacheEnabled = false; - bool _hasFilters = false; - bool _cacheFilters = false; - bool _contentStatic = false; +protected: + Layer* layer = nullptr; + bool _cacheEnabled = false; + bool _hasFilters = false; + bool _cacheFilters = false; + bool _contentStatic = false; - Content* createCache(Frame layerFrame) override; + Content* createCache(Frame layerFrame) override; - virtual ID getCacheID() const { - return layer->uniqueID; - } + virtual ID getCacheID() const { + return layer->uniqueID; + } - virtual void excludeVaryingRanges(std::vector*) const { - } - virtual GraphicContent* createContent(Frame layerFrame) const = 0; + virtual void excludeVaryingRanges(std::vector*) const { + } + virtual GraphicContent* createContent(Frame layerFrame) const = 0; - private: - bool checkCacheFilters(); - bool checkCacheEnabled(); +private: + bool checkCacheFilters(); + bool checkCacheEnabled(); }; class EmptyContentCache : public ContentCache { - public: - explicit EmptyContentCache(Layer* layer) : ContentCache(layer) { - } - - protected: - GraphicContent* createContent(Frame) const override { - return new GraphicContent(nullptr); - } +public: + explicit EmptyContentCache(Layer* layer) : ContentCache(layer) { + } + +protected: + GraphicContent* createContent(Frame) const override { + return new GraphicContent(nullptr); + } }; } // namespace pag diff --git a/src/rendering/caches/FrameCache.h b/src/rendering/caches/FrameCache.h index 4e06c5a3a9..4f48dbaa35 100644 --- a/src/rendering/caches/FrameCache.h +++ b/src/rendering/caches/FrameCache.h @@ -24,52 +24,52 @@ namespace pag { template class FrameCache : public Cache { - public: - explicit FrameCache(Frame startTime, Frame duration) : startTime(startTime), duration(duration) { - if (duration <= 0) { - this->duration = duration = 1; - } - - TimeRange range = {0, duration - 1}; - staticTimeRanges.push_back(range); - } +public: + explicit FrameCache(Frame startTime, Frame duration) : startTime(startTime), duration(duration) { + if (duration <= 0) { + this->duration = duration = 1; + } - ~FrameCache() override { - for (auto& item : frames) { - delete item.second; + TimeRange range = {0, duration - 1}; + staticTimeRanges.push_back(range); } - } - virtual T* getCache(Frame contentFrame) { - contentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, contentFrame); - if (contentFrame >= duration) { - contentFrame = duration - 1; - } - if (contentFrame < 0) { - contentFrame = 0; + ~FrameCache() override { + for (auto& item : frames) { + delete item.second; + } } - std::lock_guard autoLock(locker); - auto cache = frames[contentFrame]; - if (cache == nullptr) { - cache = createCache(contentFrame + startTime); - frames[contentFrame] = cache; + + virtual T* getCache(Frame contentFrame) { + contentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, contentFrame); + if (contentFrame >= duration) { + contentFrame = duration - 1; + } + if (contentFrame < 0) { + contentFrame = 0; + } + std::lock_guard autoLock(locker); + auto cache = frames[contentFrame]; + if (cache == nullptr) { + cache = createCache(contentFrame + startTime); + frames[contentFrame] = cache; + } + return cache; } - return cache; - } - const std::vector* getStaticTimeRanges() const { - return &staticTimeRanges; - } + const std::vector* getStaticTimeRanges() const { + return &staticTimeRanges; + } - protected: - Frame startTime = 0; - Frame duration = 1; - std::vector staticTimeRanges; +protected: + Frame startTime = 0; + Frame duration = 1; + std::vector staticTimeRanges; - virtual T* createCache(Frame layerFrame) = 0; + virtual T* createCache(Frame layerFrame) = 0; - private: - std::mutex locker = {}; - std::unordered_map frames; +private: + std::mutex locker = {}; + std::unordered_map frames; }; } // namespace pag diff --git a/src/rendering/caches/GraphicContent.cpp b/src/rendering/caches/GraphicContent.cpp index bdf8917110..0f8e3ddc31 100644 --- a/src/rendering/caches/GraphicContent.cpp +++ b/src/rendering/caches/GraphicContent.cpp @@ -25,14 +25,14 @@ GraphicContent::GraphicContent(std::shared_ptr graphic) : graphic(std:: } void GraphicContent::measureBounds(Rect* bounds) { - if (graphic) { - graphic->measureBounds(bounds); - } else { - bounds->setEmpty(); - } + if (graphic) { + graphic->measureBounds(bounds); + } else { + bounds->setEmpty(); + } } void GraphicContent::draw(Recorder* recorder) { - recorder->drawGraphic(graphic); + recorder->drawGraphic(graphic); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/GraphicContent.h b/src/rendering/caches/GraphicContent.h index c266d6fc8e..a81c4f57db 100644 --- a/src/rendering/caches/GraphicContent.h +++ b/src/rendering/caches/GraphicContent.h @@ -24,11 +24,11 @@ namespace pag { class GraphicContent : public Content { - public: - explicit GraphicContent(std::shared_ptr graphic); - void measureBounds(Rect* bounds) override; - void draw(Recorder* recorder) override; +public: + explicit GraphicContent(std::shared_ptr graphic); + void measureBounds(Rect* bounds) override; + void draw(Recorder* recorder) override; - std::shared_ptr graphic = nullptr; + std::shared_ptr graphic = nullptr; }; } // namespace pag diff --git a/src/rendering/caches/ImageContentCache.cpp b/src/rendering/caches/ImageContentCache.cpp index e308b46709..4d19edd59c 100644 --- a/src/rendering/caches/ImageContentCache.cpp +++ b/src/rendering/caches/ImageContentCache.cpp @@ -21,39 +21,39 @@ namespace pag { class ImageBytesCache : public Cache { - public: - static ImageBytesCache* Get(ImageBytes* imageBytes) { - std::lock_guard autoLock(imageBytes->locker); - if (imageBytes->cache != nullptr) { - return static_cast(imageBytes->cache); +public: + static ImageBytesCache* Get(ImageBytes* imageBytes) { + std::lock_guard autoLock(imageBytes->locker); + if (imageBytes->cache != nullptr) { + return static_cast(imageBytes->cache); + } + auto cache = new ImageBytesCache(); + auto fileBytes = + Data::MakeWithoutCopy(imageBytes->fileBytes->data(), imageBytes->fileBytes->length()); + cache->image = Image::MakeFrom(std::move(fileBytes)); + auto picture = Picture::MakeFrom(imageBytes->uniqueID, cache->image); + auto matrix = Matrix::MakeScale(1 / imageBytes->scaleFactor); + matrix.postTranslate(static_cast(-imageBytes->anchorX), + static_cast(-imageBytes->anchorY)); + cache->graphic = Graphic::MakeCompose(picture, matrix); + imageBytes->cache = cache; + return cache; } - auto cache = new ImageBytesCache(); - auto fileBytes = - Data::MakeWithoutCopy(imageBytes->fileBytes->data(), imageBytes->fileBytes->length()); - cache->image = Image::MakeFrom(std::move(fileBytes)); - auto picture = Picture::MakeFrom(imageBytes->uniqueID, cache->image); - auto matrix = Matrix::MakeScale(1 / imageBytes->scaleFactor); - matrix.postTranslate(static_cast(-imageBytes->anchorX), - static_cast(-imageBytes->anchorY)); - cache->graphic = Graphic::MakeCompose(picture, matrix); - imageBytes->cache = cache; - return cache; - } - std::shared_ptr image = nullptr; - std::shared_ptr graphic = nullptr; + std::shared_ptr image = nullptr; + std::shared_ptr graphic = nullptr; }; std::shared_ptr ImageContentCache::GetImage(ImageBytes* imageBytes) { - return ImageBytesCache::Get(imageBytes)->image; + return ImageBytesCache::Get(imageBytes)->image; } ImageContentCache::ImageContentCache(ImageLayer* layer) : ContentCache(layer) { } GraphicContent* ImageContentCache::createContent(Frame) const { - auto imageBytes = static_cast(layer)->imageBytes; - auto graphic = ImageBytesCache::Get(imageBytes)->graphic; - return new GraphicContent(graphic); + auto imageBytes = static_cast(layer)->imageBytes; + auto graphic = ImageBytesCache::Get(imageBytes)->graphic; + return new GraphicContent(graphic); } } // namespace pag diff --git a/src/rendering/caches/ImageContentCache.h b/src/rendering/caches/ImageContentCache.h index aa5a98183e..fbcbfb9fb6 100644 --- a/src/rendering/caches/ImageContentCache.h +++ b/src/rendering/caches/ImageContentCache.h @@ -22,12 +22,12 @@ namespace pag { class ImageContentCache : public ContentCache { - public: - static std::shared_ptr GetImage(ImageBytes* imageBytes); +public: + static std::shared_ptr GetImage(ImageBytes* imageBytes); - explicit ImageContentCache(ImageLayer* layer); + explicit ImageContentCache(ImageLayer* layer); - protected: - GraphicContent* createContent(Frame layerFrame) const override; +protected: + GraphicContent* createContent(Frame layerFrame) const override; }; } // namespace pag diff --git a/src/rendering/caches/LayerCache.cpp b/src/rendering/caches/LayerCache.cpp index f09d1db96e..ae4c597742 100644 --- a/src/rendering/caches/LayerCache.cpp +++ b/src/rendering/caches/LayerCache.cpp @@ -26,154 +26,154 @@ namespace pag { LayerCache* LayerCache::Get(Layer* layer) { - std::lock_guard autoLock(layer->locker); - if (layer->cache == nullptr) { - layer->cache = new LayerCache(layer); - } - return static_cast(layer->cache); + std::lock_guard autoLock(layer->locker); + if (layer->cache == nullptr) { + layer->cache = new LayerCache(layer); + } + return static_cast(layer->cache); } LayerCache::LayerCache(Layer* layer) : layer(layer) { - switch (layer->type()) { + switch (layer->type()) { case LayerType::Shape: - contentCache = new ShapeContentCache(static_cast(layer)); - break; + contentCache = new ShapeContentCache(static_cast(layer)); + break; case LayerType::Text: - contentCache = new TextContentCache(static_cast(layer)); - break; + contentCache = new TextContentCache(static_cast(layer)); + break; case LayerType::Solid: - contentCache = new SolidContentCache(static_cast(layer)); - break; + contentCache = new SolidContentCache(static_cast(layer)); + break; case LayerType::Image: - contentCache = new ImageContentCache(static_cast(layer)); - break; + contentCache = new ImageContentCache(static_cast(layer)); + break; case LayerType::PreCompose: - contentCache = new PreComposeContentCache(static_cast(layer)); - break; + contentCache = new PreComposeContentCache(static_cast(layer)); + break; default: - contentCache = new EmptyContentCache(layer); - break; - } - contentCache->update(); - transformCache = new TransformCache(layer); - if (!layer->masks.empty()) { - maskCache = new MaskCache(layer); - } - updateStaticTimeRanges(); - maxScaleFactor = layer->getMaxScaleFactor(); + contentCache = new EmptyContentCache(layer); + break; + } + contentCache->update(); + transformCache = new TransformCache(layer); + if (!layer->masks.empty()) { + maskCache = new MaskCache(layer); + } + updateStaticTimeRanges(); + maxScaleFactor = layer->getMaxScaleFactor(); } LayerCache::~LayerCache() { - delete transformCache; - delete maskCache; - delete contentCache; + delete transformCache; + delete maskCache; + delete contentCache; } Transform* LayerCache::getTransform(Frame contentFrame) { - return transformCache->getCache(contentFrame); + return transformCache->getCache(contentFrame); } Path* LayerCache::getMasks(Frame contentFrame) { - auto mask = maskCache ? maskCache->getCache(contentFrame) : nullptr; - if (mask && mask->isEmpty()) { - return nullptr; - } - return mask; + auto mask = maskCache ? maskCache->getCache(contentFrame) : nullptr; + if (mask && mask->isEmpty()) { + return nullptr; + } + return mask; } Content* LayerCache::getContent(Frame contentFrame) { - return contentCache->getCache(contentFrame); + return contentCache->getCache(contentFrame); } Layer* LayerCache::getLayer() const { - return layer; + return layer; } Point LayerCache::getMaxScaleFactor() const { - return maxScaleFactor; + return maxScaleFactor; } bool LayerCache::checkFrameChanged(Frame contentFrame, Frame lastContentFrame) { - if (contentFrame == lastContentFrame) { - return false; - } - if ((contentFrame < 0 || contentFrame >= layer->duration) && - (lastContentFrame < 0 || lastContentFrame >= layer->duration)) { - return false; - } - contentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, contentFrame); - lastContentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, lastContentFrame); - return contentFrame != lastContentFrame; + if (contentFrame == lastContentFrame) { + return false; + } + if ((contentFrame < 0 || contentFrame >= layer->duration) && + (lastContentFrame < 0 || lastContentFrame >= layer->duration)) { + return false; + } + contentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, contentFrame); + lastContentFrame = ConvertFrameByStaticTimeRanges(staticTimeRanges, lastContentFrame); + return contentFrame != lastContentFrame; } bool LayerCache::contentVisible(Frame contentFrame) { - if (contentFrame < 0 || contentFrame >= layer->duration) { - return false; - } - auto layerTransform = getTransform(contentFrame); - return layerTransform->visible(); + if (contentFrame < 0 || contentFrame >= layer->duration) { + return false; + } + auto layerTransform = getTransform(contentFrame); + return layerTransform->visible(); } void LayerCache::updateStaticTimeRanges() { - // layer->startTime is excluded from all time ranges. - if (layer->type() == LayerType::PreCompose && - static_cast(layer)->composition->type() == CompositionType::Vector) { - // 矢量预合成的内容静态区间包含了子项, - // 这里的 staticTimeRanges 只记录 Layer 自身的静态区间, - // 避免在 Layer->gotoFrame() 里重复判断非真实子项的帧号变化。 - TimeRange range = {0, layer->duration - 1}; - staticTimeRanges.push_back(range); - } else { - staticTimeRanges = *contentCache->getStaticTimeRanges(); - } - MergeTimeRanges(&staticTimeRanges, transformCache->getStaticTimeRanges()); - if (maskCache) { - MergeTimeRanges(&staticTimeRanges, maskCache->getStaticTimeRanges()); - } - if (layer->trackMatteLayer) { - auto timeRanges = getTrackMatteStaticTimeRanges(); - MergeTimeRanges(&staticTimeRanges, &timeRanges); - } - if (!layer->layerStyles.empty() || !layer->effects.empty()) { - auto timeRanges = getFilterStaticTimeRanges(); - MergeTimeRanges(&staticTimeRanges, &timeRanges); - } - if (layer->motionBlur) { - // MotionBlur是根据Transform来处理图像, - // 如果staticTransformRanges中的start帧被加上MotionBlur的效果 - // (start - 1帧到start帧之间有Transform),但后续因为静态空间的计算, - // 不重新绘制该图层,导致后续静态区间里一直显示带有MotionBlur的效果, - // 但实际是不需要带有MotionBlur,因此需要在LayerCache的staticTimeRanges过滤掉静态区间的第一帧。 - for (auto& timeRange : *transformCache->getStaticTimeRanges()) { - SplitTimeRangesAt(&staticTimeRanges, timeRange.start + 1); + // layer->startTime is excluded from all time ranges. + if (layer->type() == LayerType::PreCompose && + static_cast(layer)->composition->type() == CompositionType::Vector) { + // 矢量预合成的内容静态区间包含了子项, + // 这里的 staticTimeRanges 只记录 Layer 自身的静态区间, + // 避免在 Layer->gotoFrame() 里重复判断非真实子项的帧号变化。 + TimeRange range = {0, layer->duration - 1}; + staticTimeRanges.push_back(range); + } else { + staticTimeRanges = *contentCache->getStaticTimeRanges(); + } + MergeTimeRanges(&staticTimeRanges, transformCache->getStaticTimeRanges()); + if (maskCache) { + MergeTimeRanges(&staticTimeRanges, maskCache->getStaticTimeRanges()); + } + if (layer->trackMatteLayer) { + auto timeRanges = getTrackMatteStaticTimeRanges(); + MergeTimeRanges(&staticTimeRanges, &timeRanges); + } + if (!layer->layerStyles.empty() || !layer->effects.empty()) { + auto timeRanges = getFilterStaticTimeRanges(); + MergeTimeRanges(&staticTimeRanges, &timeRanges); + } + if (layer->motionBlur) { + // MotionBlur是根据Transform来处理图像, + // 如果staticTransformRanges中的start帧被加上MotionBlur的效果 + // (start - 1帧到start帧之间有Transform),但后续因为静态空间的计算, + // 不重新绘制该图层,导致后续静态区间里一直显示带有MotionBlur的效果, + // 但实际是不需要带有MotionBlur,因此需要在LayerCache的staticTimeRanges过滤掉静态区间的第一帧。 + for (auto& timeRange : *transformCache->getStaticTimeRanges()) { + SplitTimeRangesAt(&staticTimeRanges, timeRange.start + 1); + } } - } } std::vector LayerCache::getTrackMatteStaticTimeRanges() { - auto trackMatteLayer = layer->trackMatteLayer; - std::vector timeRanges = {trackMatteLayer->visibleRange()}; - trackMatteLayer->excludeVaryingRanges(&timeRanges); - SplitTimeRangesAt(&timeRanges, trackMatteLayer->startTime); - SplitTimeRangesAt(&timeRanges, trackMatteLayer->startTime + trackMatteLayer->duration); - auto parent = trackMatteLayer->parent; - while (parent != nullptr) { - parent->transform->excludeVaryingRanges(&timeRanges); - SplitTimeRangesAt(&timeRanges, parent->startTime); - SplitTimeRangesAt(&timeRanges, parent->startTime + parent->duration); - parent = parent->parent; - } - return OffsetTimeRanges(timeRanges, -layer->startTime); + auto trackMatteLayer = layer->trackMatteLayer; + std::vector timeRanges = {trackMatteLayer->visibleRange()}; + trackMatteLayer->excludeVaryingRanges(&timeRanges); + SplitTimeRangesAt(&timeRanges, trackMatteLayer->startTime); + SplitTimeRangesAt(&timeRanges, trackMatteLayer->startTime + trackMatteLayer->duration); + auto parent = trackMatteLayer->parent; + while (parent != nullptr) { + parent->transform->excludeVaryingRanges(&timeRanges); + SplitTimeRangesAt(&timeRanges, parent->startTime); + SplitTimeRangesAt(&timeRanges, parent->startTime + parent->duration); + parent = parent->parent; + } + return OffsetTimeRanges(timeRanges, -layer->startTime); } std::vector LayerCache::getFilterStaticTimeRanges() { - std::vector timeRanges = {layer->visibleRange()}; - for (auto& layerStyle : layer->layerStyles) { - layerStyle->excludeVaryingRanges(&timeRanges); - } - for (auto& effect : layer->effects) { - effect->excludeVaryingRanges(&timeRanges); - } - return OffsetTimeRanges(timeRanges, -layer->startTime); + std::vector timeRanges = {layer->visibleRange()}; + for (auto& layerStyle : layer->layerStyles) { + layerStyle->excludeVaryingRanges(&timeRanges); + } + for (auto& effect : layer->effects) { + effect->excludeVaryingRanges(&timeRanges); + } + return OffsetTimeRanges(timeRanges, -layer->startTime); } } // namespace pag diff --git a/src/rendering/caches/LayerCache.h b/src/rendering/caches/LayerCache.h index 2778c06190..fcc9b1b4ce 100644 --- a/src/rendering/caches/LayerCache.h +++ b/src/rendering/caches/LayerCache.h @@ -24,52 +24,52 @@ namespace pag { class LayerCache : public Cache { - public: - static LayerCache* Get(Layer* layer); +public: + static LayerCache* Get(Layer* layer); - ~LayerCache() override; + ~LayerCache() override; - Transform* getTransform(Frame contentFrame); + Transform* getTransform(Frame contentFrame); - Path* getMasks(Frame contentFrame); + Path* getMasks(Frame contentFrame); - Content* getContent(Frame contentFrame); + Content* getContent(Frame contentFrame); - Layer* getLayer() const; + Layer* getLayer() const; - Point getMaxScaleFactor() const; + Point getMaxScaleFactor() const; - bool checkFrameChanged(Frame contentFrame, Frame lastContentFrame); + bool checkFrameChanged(Frame contentFrame, Frame lastContentFrame); - bool contentVisible(Frame contentFrame); + bool contentVisible(Frame contentFrame); - bool contentStatic() const { - return contentCache->contentStatic(); - } + bool contentStatic() const { + return contentCache->contentStatic(); + } - bool cacheEnabled() const { - return contentCache->cacheEnabled(); - } + bool cacheEnabled() const { + return contentCache->cacheEnabled(); + } - bool hasFilters() const { - return contentCache->hasFilters(); - } + bool hasFilters() const { + return contentCache->hasFilters(); + } - bool cacheFilters() const { - return contentCache->cacheFilters(); - } + bool cacheFilters() const { + return contentCache->cacheFilters(); + } - private: - Layer* layer = nullptr; - TransformCache* transformCache = nullptr; - MaskCache* maskCache = nullptr; - ContentCache* contentCache = nullptr; - Point maxScaleFactor = {}; - std::vector staticTimeRanges; +private: + Layer* layer = nullptr; + TransformCache* transformCache = nullptr; + MaskCache* maskCache = nullptr; + ContentCache* contentCache = nullptr; + Point maxScaleFactor = {}; + std::vector staticTimeRanges; - explicit LayerCache(Layer* layer); - void updateStaticTimeRanges(); - std::vector getTrackMatteStaticTimeRanges(); - std::vector getFilterStaticTimeRanges(); + explicit LayerCache(Layer* layer); + void updateStaticTimeRanges(); + std::vector getTrackMatteStaticTimeRanges(); + std::vector getFilterStaticTimeRanges(); }; } // namespace pag diff --git a/src/rendering/caches/MaskCache.cpp b/src/rendering/caches/MaskCache.cpp index 1baef84e56..d68b4820fa 100644 --- a/src/rendering/caches/MaskCache.cpp +++ b/src/rendering/caches/MaskCache.cpp @@ -22,16 +22,16 @@ namespace pag { MaskCache::MaskCache(Layer* layer) : FrameCache(layer->startTime, layer->duration), layer(layer) { - std::vector timeRanges = {layer->visibleRange()}; - for (auto& mask : layer->masks) { - mask->excludeVaryingRanges(&timeRanges); - } - staticTimeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); + std::vector timeRanges = {layer->visibleRange()}; + for (auto& mask : layer->masks) { + mask->excludeVaryingRanges(&timeRanges); + } + staticTimeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); } Path* MaskCache::createCache(Frame layerFrame) { - auto maskContent = new Path(); - RenderMasks(maskContent, layer->masks, layerFrame); - return maskContent; + auto maskContent = new Path(); + RenderMasks(maskContent, layer->masks, layerFrame); + return maskContent; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/MaskCache.h b/src/rendering/caches/MaskCache.h index 20d7a4827a..311b0ccafc 100644 --- a/src/rendering/caches/MaskCache.h +++ b/src/rendering/caches/MaskCache.h @@ -23,13 +23,13 @@ namespace pag { class MaskCache : public FrameCache { - public: - explicit MaskCache(Layer* layer); +public: + explicit MaskCache(Layer* layer); - protected: - Path* createCache(Frame layerFrame) override; +protected: + Path* createCache(Frame layerFrame) override; - private: - Layer* layer = nullptr; +private: + Layer* layer = nullptr; }; } // namespace pag diff --git a/src/rendering/caches/PreComposeContentCache.cpp b/src/rendering/caches/PreComposeContentCache.cpp index a99c5f0892..497d83f4e3 100644 --- a/src/rendering/caches/PreComposeContentCache.cpp +++ b/src/rendering/caches/PreComposeContentCache.cpp @@ -22,16 +22,16 @@ namespace pag { PreComposeContentCache::PreComposeContentCache(PreComposeLayer* layer) : ContentCache(layer) { - compositionCache = CompositionCache::Get(layer->composition); + compositionCache = CompositionCache::Get(layer->composition); } void PreComposeContentCache::excludeVaryingRanges(std::vector* timeRanges) const { - *timeRanges = static_cast(layer)->getContentStaticTimeRanges(); + *timeRanges = static_cast(layer)->getContentStaticTimeRanges(); } GraphicContent* PreComposeContentCache::createContent(Frame layerFrame) const { - auto compositionFrame = static_cast(layer)->getCompositionFrame(layerFrame); - auto graphic = compositionCache->getContent(compositionFrame); - return new GraphicContent(graphic); + auto compositionFrame = static_cast(layer)->getCompositionFrame(layerFrame); + auto graphic = compositionCache->getContent(compositionFrame); + return new GraphicContent(graphic); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/PreComposeContentCache.h b/src/rendering/caches/PreComposeContentCache.h index 07ac101804..29914198fb 100644 --- a/src/rendering/caches/PreComposeContentCache.h +++ b/src/rendering/caches/PreComposeContentCache.h @@ -23,14 +23,14 @@ namespace pag { class PreComposeContentCache : public ContentCache { - public: - explicit PreComposeContentCache(PreComposeLayer* layer); +public: + explicit PreComposeContentCache(PreComposeLayer* layer); - protected: - void excludeVaryingRanges(std::vector*) const override; - GraphicContent* createContent(Frame layerFrame) const override; +protected: + void excludeVaryingRanges(std::vector*) const override; + GraphicContent* createContent(Frame layerFrame) const override; - private: - CompositionCache* compositionCache = nullptr; +private: + CompositionCache* compositionCache = nullptr; }; } // namespace pag diff --git a/src/rendering/caches/RenderCache.cpp b/src/rendering/caches/RenderCache.cpp index b141541019..d37a56965c 100644 --- a/src/rendering/caches/RenderCache.cpp +++ b/src/rendering/caches/RenderCache.cpp @@ -36,490 +36,490 @@ namespace pag { #define MIN_HARDWARE_PREPARE_TIME 100000 // 距离当前时刻小于100ms的视频启动软解转硬解优化。 class ImageTask : public Executor { - public: - static std::shared_ptr MakeAndRun(std::shared_ptr image) { - if (image == nullptr) { - return nullptr; - } - auto bitmap = new ImageTask(std::move(image)); - auto task = Task::Make(std::unique_ptr(bitmap)); - task->run(); - return task; - } - - std::shared_ptr getBuffer() const { - return buffer; - } - - private: - std::shared_ptr buffer = {}; - std::shared_ptr image = nullptr; - - explicit ImageTask(std::shared_ptr image) : image(std::move(image)) { - } - - void execute() override { - buffer = image->makeBuffer(); - } +public: + static std::shared_ptr MakeAndRun(std::shared_ptr image) { + if (image == nullptr) { + return nullptr; + } + auto bitmap = new ImageTask(std::move(image)); + auto task = Task::Make(std::unique_ptr(bitmap)); + task->run(); + return task; + } + + std::shared_ptr getBuffer() const { + return buffer; + } + +private: + std::shared_ptr buffer = {}; + std::shared_ptr image = nullptr; + + explicit ImageTask(std::shared_ptr image) : image(std::move(image)) { + } + + void execute() override { + buffer = image->makeBuffer(); + } }; RenderCache::RenderCache(PAGStage* stage) : _uniqueID(UniqueID::Next()), stage(stage) { } RenderCache::~RenderCache() { - releaseAll(); + releaseAll(); } uint32_t RenderCache::getContentVersion() const { - return stage->getContentVersion(); + return stage->getContentVersion(); } bool RenderCache::videoEnabled() const { - return _videoEnabled; + return _videoEnabled; } void RenderCache::setVideoEnabled(bool value) { - if (_videoEnabled == value) { - return; - } - _videoEnabled = value; - clearAllSequenceCaches(); + if (_videoEnabled == value) { + return; + } + _videoEnabled = value; + clearAllSequenceCaches(); } bool RenderCache::initFilter(Filter* filter) { - auto startTime = GetTimer(); - auto result = filter->initialize(getContext()); - programCompilingTime += GetTimer() - startTime; - return result; + auto startTime = GetTimer(); + auto result = filter->initialize(getContext()); + programCompilingTime += GetTimer() - startTime; + return result; } void RenderCache::preparePreComposeLayer(PreComposeLayer* layer, DecodingPolicy policy) { - auto composition = layer->composition; - if (composition->type() != CompositionType::Video && - composition->type() != CompositionType::Bitmap) { - return; - } - auto timeScale = layer->containingComposition - ? (composition->frameRate / layer->containingComposition->frameRate) - : 1.0f; - auto compositionFrame = static_cast( - roundf(static_cast(layer->startTime - layer->compositionStartTime) * timeScale)); - if (compositionFrame < 0) { - compositionFrame = 0; - } - auto sequence = Sequence::Get(composition); - auto sequenceFrame = sequence->toSequenceFrame(compositionFrame); - if (prepareSequenceReader(sequence, sequenceFrame, policy)) { - return; - } - auto result = sequenceCaches.find(composition->uniqueID); - if (result != sequenceCaches.end()) { - // 循环预测 - result->second->prepareAsync(sequenceFrame); - } + auto composition = layer->composition; + if (composition->type() != CompositionType::Video && + composition->type() != CompositionType::Bitmap) { + return; + } + auto timeScale = layer->containingComposition + ? (composition->frameRate / layer->containingComposition->frameRate) + : 1.0f; + auto compositionFrame = static_cast( + roundf(static_cast(layer->startTime - layer->compositionStartTime) * timeScale)); + if (compositionFrame < 0) { + compositionFrame = 0; + } + auto sequence = Sequence::Get(composition); + auto sequenceFrame = sequence->toSequenceFrame(compositionFrame); + if (prepareSequenceReader(sequence, sequenceFrame, policy)) { + return; + } + auto result = sequenceCaches.find(composition->uniqueID); + if (result != sequenceCaches.end()) { + // 循环预测 + result->second->prepareAsync(sequenceFrame); + } } void RenderCache::prepareImageLayer(PAGImageLayer* pagLayer) { - auto pagImage = static_cast(pagLayer)->getPAGImage(); - if (pagImage == nullptr) { - auto imageBytes = static_cast(pagLayer->layer)->imageBytes; - auto image = ImageContentCache::GetImage(imageBytes); + auto pagImage = static_cast(pagLayer)->getPAGImage(); + if (pagImage == nullptr) { + auto imageBytes = static_cast(pagLayer->layer)->imageBytes; + auto image = ImageContentCache::GetImage(imageBytes); + if (image) { + prepareImage(imageBytes->uniqueID, image); + } + return; + } + auto image = pagImage->getImage(); if (image) { - prepareImage(imageBytes->uniqueID, image); + prepareImage(pagImage->uniqueID(), image); } - return; - } - auto image = pagImage->getImage(); - if (image) { - prepareImage(pagImage->uniqueID(), image); - } } void RenderCache::clearExpiredSequences() { - std::vector expiredSequences = {}; - for (auto& item : sequenceCaches) { - if (usedAssets.count(item.first) == 0) { - expiredSequences.push_back(item.first); + std::vector expiredSequences = {}; + for (auto& item : sequenceCaches) { + if (usedAssets.count(item.first) == 0) { + expiredSequences.push_back(item.first); + } + } + for (auto& id : expiredSequences) { + clearSequenceCache(id); } - } - for (auto& id : expiredSequences) { - clearSequenceCache(id); - } } bool RenderCache::snapshotEnabled() const { - return _snapshotEnabled; + return _snapshotEnabled; } void RenderCache::setSnapshotEnabled(bool value) { - if (_snapshotEnabled == value) { - return; - } - _snapshotEnabled = value; - clearAllSnapshots(); + if (_snapshotEnabled == value) { + return; + } + _snapshotEnabled = value; + clearAllSnapshots(); } void RenderCache::prepareFrame() { - usedAssets = {}; - resetPerformance(); - auto layerDistances = stage->findNearlyVisibleLayersIn(DECODING_VISIBLE_DISTANCE); - for (auto& item : layerDistances) { - for (auto pagLayer : item.second) { - if (pagLayer->layerType() == LayerType::PreCompose) { - auto policy = item.first < MIN_HARDWARE_PREPARE_TIME ? DecodingPolicy::SoftwareToHardware - : DecodingPolicy::Hardware; - preparePreComposeLayer(static_cast(pagLayer->layer), policy); - } else if (pagLayer->layerType() == LayerType::Image) { - prepareImageLayer(static_cast(pagLayer)); - } - } - } + usedAssets = {}; + resetPerformance(); + auto layerDistances = stage->findNearlyVisibleLayersIn(DECODING_VISIBLE_DISTANCE); + for (auto& item : layerDistances) { + for (auto pagLayer : item.second) { + if (pagLayer->layerType() == LayerType::PreCompose) { + auto policy = item.first < MIN_HARDWARE_PREPARE_TIME ? DecodingPolicy::SoftwareToHardware + : DecodingPolicy::Hardware; + preparePreComposeLayer(static_cast(pagLayer->layer), policy); + } else if (pagLayer->layerType() == LayerType::Image) { + prepareImageLayer(static_cast(pagLayer)); + } + } + } } void RenderCache::attachToContext(Context* current, bool forHitTest) { - if (deviceID > 0 && deviceID != current->getDevice()->uniqueID()) { - // Context 改变需要清理内部所有缓存,这里用 uniqueID - // 而不用指针比较,是因为指针析构后再创建可能会地址重合。 - releaseAll(); - } - context = current; - deviceID = context->getDevice()->uniqueID(); - hitTestOnly = forHitTest; - if (hitTestOnly) { - return; - } - auto removedAssets = stage->getRemovedAssets(); - for (auto assetID : removedAssets) { - removeSnapshot(assetID); - imageTasks.erase(assetID); - clearSequenceCache(assetID); - clearFilterCache(assetID); - } + if (deviceID > 0 && deviceID != current->getDevice()->uniqueID()) { + // Context 改变需要清理内部所有缓存,这里用 uniqueID + // 而不用指针比较,是因为指针析构后再创建可能会地址重合。 + releaseAll(); + } + context = current; + deviceID = context->getDevice()->uniqueID(); + hitTestOnly = forHitTest; + if (hitTestOnly) { + return; + } + auto removedAssets = stage->getRemovedAssets(); + for (auto assetID : removedAssets) { + removeSnapshot(assetID); + imageTasks.erase(assetID); + clearSequenceCache(assetID); + clearFilterCache(assetID); + } } void RenderCache::releaseAll() { - clearAllSnapshots(); - graphicsMemory = 0; - clearAllSequenceCaches(); - for (auto& item : filterCaches) { - delete item.second; - } - filterCaches.clear(); - delete motionBlurFilter; - motionBlurFilter = nullptr; - deviceID = 0; + clearAllSnapshots(); + graphicsMemory = 0; + clearAllSequenceCaches(); + for (auto& item : filterCaches) { + delete item.second; + } + filterCaches.clear(); + delete motionBlurFilter; + motionBlurFilter = nullptr; + deviceID = 0; } void RenderCache::detachFromContext() { - if (hitTestOnly) { + if (hitTestOnly) { + context = nullptr; + return; + } + clearExpiredSequences(); + clearExpiredBitmaps(); + clearExpiredSnapshots(); + auto currentTimestamp = GetTimer(); + context->purgeResourcesNotUsedIn(currentTimestamp - lastTimestamp); + lastTimestamp = currentTimestamp; context = nullptr; - return; - } - clearExpiredSequences(); - clearExpiredBitmaps(); - clearExpiredSnapshots(); - auto currentTimestamp = GetTimer(); - context->purgeResourcesNotUsedIn(currentTimestamp - lastTimestamp); - lastTimestamp = currentTimestamp; - context = nullptr; } Snapshot* RenderCache::getSnapshot(ID assetID) const { - if (!_snapshotEnabled) { + if (!_snapshotEnabled) { + return nullptr; + } + auto result = snapshotCaches.find(assetID); + if (result != snapshotCaches.end()) { + return result->second; + } return nullptr; - } - auto result = snapshotCaches.find(assetID); - if (result != snapshotCaches.end()) { - return result->second; - } - return nullptr; } Snapshot* RenderCache::getSnapshot(const Picture* image) { - if (!_snapshotEnabled) { - return nullptr; - } - usedAssets.insert(image->assetID); - auto maxScaleFactor = stage->getAssetMaxScale(image->assetID); - auto scaleFactor = image->getScaleFactor(maxScaleFactor); - auto snapshot = getSnapshot(image->assetID); - if (snapshot && (snapshot->makerKey != image->uniqueKey || - fabsf(snapshot->scaleFactor() - scaleFactor) > SCALE_FACTOR_PRECISION)) { - removeSnapshot(image->assetID); - snapshot = nullptr; - } - if (snapshot) { - snapshot->idleFrames = 0; - auto position = std::find(snapshotLRU.begin(), snapshotLRU.end(), snapshot); - if (position != snapshotLRU.end()) { - snapshotLRU.erase(position); + if (!_snapshotEnabled) { + return nullptr; + } + usedAssets.insert(image->assetID); + auto maxScaleFactor = stage->getAssetMaxScale(image->assetID); + auto scaleFactor = image->getScaleFactor(maxScaleFactor); + auto snapshot = getSnapshot(image->assetID); + if (snapshot && (snapshot->makerKey != image->uniqueKey || + fabsf(snapshot->scaleFactor() - scaleFactor) > SCALE_FACTOR_PRECISION)) { + removeSnapshot(image->assetID); + snapshot = nullptr; + } + if (snapshot) { + snapshot->idleFrames = 0; + auto position = std::find(snapshotLRU.begin(), snapshotLRU.end(), snapshot); + if (position != snapshotLRU.end()) { + snapshotLRU.erase(position); + } + snapshotLRU.push_front(snapshot); + return snapshot; } + if (scaleFactor < SCALE_FACTOR_PRECISION || graphicsMemory >= MAX_GRAPHICS_MEMORY) { + return nullptr; + } + auto newSnapshot = image->makeSnapshot(this, scaleFactor); + if (newSnapshot == nullptr) { + return nullptr; + } + snapshot = newSnapshot.release(); + snapshot->assetID = image->assetID; + snapshot->makerKey = image->uniqueKey; + graphicsMemory += snapshot->memoryUsage(); snapshotLRU.push_front(snapshot); + snapshotCaches[image->assetID] = snapshot; return snapshot; - } - if (scaleFactor < SCALE_FACTOR_PRECISION || graphicsMemory >= MAX_GRAPHICS_MEMORY) { - return nullptr; - } - auto newSnapshot = image->makeSnapshot(this, scaleFactor); - if (newSnapshot == nullptr) { - return nullptr; - } - snapshot = newSnapshot.release(); - snapshot->assetID = image->assetID; - snapshot->makerKey = image->uniqueKey; - graphicsMemory += snapshot->memoryUsage(); - snapshotLRU.push_front(snapshot); - snapshotCaches[image->assetID] = snapshot; - return snapshot; } void RenderCache::removeSnapshot(ID assetID) { - auto snapshot = snapshotCaches.find(assetID); - if (snapshot == snapshotCaches.end()) { - return; - } - auto position = std::find(snapshotLRU.begin(), snapshotLRU.end(), snapshot->second); - if (position != snapshotLRU.end()) { - snapshotLRU.erase(position); - } - graphicsMemory -= snapshot->second->memoryUsage(); - delete snapshot->second; - snapshotCaches.erase(assetID); + auto snapshot = snapshotCaches.find(assetID); + if (snapshot == snapshotCaches.end()) { + return; + } + auto position = std::find(snapshotLRU.begin(), snapshotLRU.end(), snapshot->second); + if (position != snapshotLRU.end()) { + snapshotLRU.erase(position); + } + graphicsMemory -= snapshot->second->memoryUsage(); + delete snapshot->second; + snapshotCaches.erase(assetID); } void RenderCache::clearAllSnapshots() { - for (auto& item : snapshotCaches) { - graphicsMemory -= item.second->memoryUsage(); - delete item.second; - } - snapshotCaches.clear(); - snapshotLRU.clear(); + for (auto& item : snapshotCaches) { + graphicsMemory -= item.second->memoryUsage(); + delete item.second; + } + snapshotCaches.clear(); + snapshotLRU.clear(); } void RenderCache::clearExpiredSnapshots() { - while (!snapshotLRU.empty()) { - auto snapshot = snapshotLRU.back(); - // 只有 Snapshot 数量可能会比较多,使用 LRU - // 来避免遍历完整的列表,遇到第一个用过的就可以取消遍历。 - if (usedAssets.count((snapshot->assetID) > 0)) { - break; + while (!snapshotLRU.empty()) { + auto snapshot = snapshotLRU.back(); + // 只有 Snapshot 数量可能会比较多,使用 LRU + // 来避免遍历完整的列表,遇到第一个用过的就可以取消遍历。 + if (usedAssets.count((snapshot->assetID) > 0)) { + break; + } + snapshot->idleFrames++; + if (snapshot->idleFrames < PURGEABLE_EXPIRED_FRAME && + graphicsMemory < PURGEABLE_GRAPHICS_MEMORY) { + // 总显存占用未超过20M且所有缓存均未超过10帧未使用,跳过清理。 + break; + } + removeSnapshot(snapshot->assetID); } - snapshot->idleFrames++; - if (snapshot->idleFrames < PURGEABLE_EXPIRED_FRAME && - graphicsMemory < PURGEABLE_GRAPHICS_MEMORY) { - // 总显存占用未超过20M且所有缓存均未超过10帧未使用,跳过清理。 - break; - } - removeSnapshot(snapshot->assetID); - } } void RenderCache::prepareImage(ID assetID, std::shared_ptr image) { - usedAssets.insert(assetID); - if (imageTasks.count(assetID) != 0 || snapshotCaches.count(assetID) != 0) { - return; - } - auto task = ImageTask::MakeAndRun(std::move(image)); - if (task) { - imageTasks[assetID] = task; - } + usedAssets.insert(assetID); + if (imageTasks.count(assetID) != 0 || snapshotCaches.count(assetID) != 0) { + return; + } + auto task = ImageTask::MakeAndRun(std::move(image)); + if (task) { + imageTasks[assetID] = task; + } } std::shared_ptr RenderCache::getImageBuffer(ID assetID) { - usedAssets.insert(assetID); - auto result = imageTasks.find(assetID); - if (result != imageTasks.end()) { - auto executor = result->second->wait(); - auto buffer = static_cast(executor)->getBuffer(); - // 预测生成的 Bitmap 取了一次就应该销毁,上层会进行缓存。 - imageTasks.erase(result); - return buffer; - } - return {}; + usedAssets.insert(assetID); + auto result = imageTasks.find(assetID); + if (result != imageTasks.end()) { + auto executor = result->second->wait(); + auto buffer = static_cast(executor)->getBuffer(); + // 预测生成的 Bitmap 取了一次就应该销毁,上层会进行缓存。 + imageTasks.erase(result); + return buffer; + } + return {}; } void RenderCache::clearExpiredBitmaps() { - std::vector expiredBitmaps = {}; - for (auto& item : imageTasks) { - if (usedAssets.count(item.first) == 0) { - expiredBitmaps.push_back(item.first); + std::vector expiredBitmaps = {}; + for (auto& item : imageTasks) { + if (usedAssets.count(item.first) == 0) { + expiredBitmaps.push_back(item.first); + } + } + for (auto& bitmapID : expiredBitmaps) { + imageTasks.erase(bitmapID); } - } - for (auto& bitmapID : expiredBitmaps) { - imageTasks.erase(bitmapID); - } } static std::shared_ptr MakeSequenceReader(std::shared_ptr file, - Sequence* sequence, - DecodingPolicy policy) { - std::shared_ptr reader = nullptr; - if (sequence->composition->type() == CompositionType::Video) { - if (sequence->composition->staticContent()) { - // 全静态的序列帧强制软件解码。 - policy = DecodingPolicy::Software; - } - reader = SequenceReader::Make(std::move(file), static_cast(sequence), policy); - } else { - reader = std::make_shared(std::move(file), - static_cast(sequence)); - } - return reader; + Sequence* sequence, + DecodingPolicy policy) { + std::shared_ptr reader = nullptr; + if (sequence->composition->type() == CompositionType::Video) { + if (sequence->composition->staticContent()) { + // 全静态的序列帧强制软件解码。 + policy = DecodingPolicy::Software; + } + reader = SequenceReader::Make(std::move(file), static_cast(sequence), policy); + } else { + reader = std::make_shared(std::move(file), + static_cast(sequence)); + } + return reader; } //===================================== sequence caches ===================================== bool RenderCache::prepareSequenceReader(Sequence* sequence, Frame targetFrame, DecodingPolicy policy) { - auto composition = sequence->composition; - if (!_videoEnabled && composition->type() == CompositionType::Video) { - return false; - } - usedAssets.insert(composition->uniqueID); - auto staticComposition = composition->staticContent(); - if (sequenceCaches.count(composition->uniqueID) != 0) { + auto composition = sequence->composition; + if (!_videoEnabled && composition->type() == CompositionType::Video) { + return false; + } + usedAssets.insert(composition->uniqueID); + auto staticComposition = composition->staticContent(); + if (sequenceCaches.count(composition->uniqueID) != 0) { #ifdef PAG_BUILD_FOR_WEB - sequenceCaches[composition->uniqueID]->prepareAsync(targetFrame); + sequenceCaches[composition->uniqueID]->prepareAsync(targetFrame); #endif - return false; - } - if (staticComposition && hasSnapshot(composition->uniqueID)) { - // 静态的序列帧采用位图的缓存逻辑,如果上层缓存过 Snapshot 就不需要预测。 - return false; - } - auto file = stage->getSequenceFile(sequence); - auto reader = MakeSequenceReader(file, sequence, policy); - sequenceCaches[composition->uniqueID] = reader; - reader->prepareAsync(targetFrame); - return true; + return false; + } + if (staticComposition && hasSnapshot(composition->uniqueID)) { + // 静态的序列帧采用位图的缓存逻辑,如果上层缓存过 Snapshot 就不需要预测。 + return false; + } + auto file = stage->getSequenceFile(sequence); + auto reader = MakeSequenceReader(file, sequence, policy); + sequenceCaches[composition->uniqueID] = reader; + reader->prepareAsync(targetFrame); + return true; } std::shared_ptr RenderCache::getSequenceReader(Sequence* sequence) { - if (sequence == nullptr) { - return nullptr; - } - auto composition = sequence->composition; - if (!_videoEnabled && composition->type() == CompositionType::Video) { - return nullptr; - } - auto compositionID = composition->uniqueID; - usedAssets.insert(compositionID); - auto staticComposition = sequence->composition->staticContent(); - std::shared_ptr reader = nullptr; - auto result = sequenceCaches.find(compositionID); - if (result != sequenceCaches.end()) { - reader = result->second; - if (reader->getSequence() != sequence) { - clearSequenceCache(compositionID); - reader = nullptr; - } else if (staticComposition) { - // 完全静态的序列帧是预测生成的,第一次访问时就可以移除,上层会进行缓存。 - sequenceCaches.erase(result); - } - } - if (reader == nullptr) { - auto file = stage->getSequenceFile(sequence); - reader = MakeSequenceReader(file, sequence, DecodingPolicy::SoftwareToHardware); - if (reader && !staticComposition) { - // 完全静态的序列帧不用缓存。 - sequenceCaches[compositionID] = reader; + if (sequence == nullptr) { + return nullptr; + } + auto composition = sequence->composition; + if (!_videoEnabled && composition->type() == CompositionType::Video) { + return nullptr; } - } - return reader; + auto compositionID = composition->uniqueID; + usedAssets.insert(compositionID); + auto staticComposition = sequence->composition->staticContent(); + std::shared_ptr reader = nullptr; + auto result = sequenceCaches.find(compositionID); + if (result != sequenceCaches.end()) { + reader = result->second; + if (reader->getSequence() != sequence) { + clearSequenceCache(compositionID); + reader = nullptr; + } else if (staticComposition) { + // 完全静态的序列帧是预测生成的,第一次访问时就可以移除,上层会进行缓存。 + sequenceCaches.erase(result); + } + } + if (reader == nullptr) { + auto file = stage->getSequenceFile(sequence); + reader = MakeSequenceReader(file, sequence, DecodingPolicy::SoftwareToHardware); + if (reader && !staticComposition) { + // 完全静态的序列帧不用缓存。 + sequenceCaches[compositionID] = reader; + } + } + return reader; } void RenderCache::clearAllSequenceCaches() { - for (auto& item : sequenceCaches) { - removeSnapshot(item.first); - } - sequenceCaches.clear(); + for (auto& item : sequenceCaches) { + removeSnapshot(item.first); + } + sequenceCaches.clear(); } void RenderCache::clearSequenceCache(ID uniqueID) { - auto result = sequenceCaches.find(uniqueID); - if (result != sequenceCaches.end()) { - removeSnapshot(result->first); - sequenceCaches.erase(result); - } + auto result = sequenceCaches.find(uniqueID); + if (result != sequenceCaches.end()) { + removeSnapshot(result->first); + sequenceCaches.erase(result); + } } //===================================== filter caches ===================================== LayerFilter* RenderCache::getFilterCache(LayerStyle* layerStyle) { - return getLayerFilterCache(layerStyle->uniqueID, [=]() -> LayerFilter* { - return LayerFilter::Make(layerStyle).release(); - }); + return getLayerFilterCache(layerStyle->uniqueID, [=]() -> LayerFilter* { + return LayerFilter::Make(layerStyle).release(); + }); } LayerFilter* RenderCache::getFilterCache(Effect* effect) { - return getLayerFilterCache(effect->uniqueID, - [=]() -> LayerFilter* { return LayerFilter::Make(effect).release(); }); + return getLayerFilterCache(effect->uniqueID, + [=]() -> LayerFilter* { return LayerFilter::Make(effect).release(); }); } LayerFilter* RenderCache::getLayerFilterCache(ID uniqueID, - const std::function& makeFilter) { - LayerFilter* filter = nullptr; - auto result = filterCaches.find(uniqueID); - if (result == filterCaches.end()) { - filter = makeFilter(); - if (filter && !initFilter(filter)) { - delete filter; - filter = nullptr; - } - if (filter != nullptr) { - filterCaches.insert(std::make_pair(uniqueID, filter)); + const std::function& makeFilter) { + LayerFilter* filter = nullptr; + auto result = filterCaches.find(uniqueID); + if (result == filterCaches.end()) { + filter = makeFilter(); + if (filter && !initFilter(filter)) { + delete filter; + filter = nullptr; + } + if (filter != nullptr) { + filterCaches.insert(std::make_pair(uniqueID, filter)); + } + } else { + filter = static_cast(result->second); } - } else { - filter = static_cast(result->second); - } - return filter; + return filter; } MotionBlurFilter* RenderCache::getMotionBlurFilter() { - if (motionBlurFilter == nullptr) { - motionBlurFilter = new MotionBlurFilter(); - if (!initFilter(motionBlurFilter)) { - delete motionBlurFilter; - motionBlurFilter = nullptr; + if (motionBlurFilter == nullptr) { + motionBlurFilter = new MotionBlurFilter(); + if (!initFilter(motionBlurFilter)) { + delete motionBlurFilter; + motionBlurFilter = nullptr; + } } - } - return motionBlurFilter; + return motionBlurFilter; } LayerStylesFilter* RenderCache::getLayerStylesFilter(Layer* layer) { - LayerStylesFilter* filter = nullptr; - auto result = filterCaches.find(layer->uniqueID); - if (result == filterCaches.end()) { - filter = new LayerStylesFilter(this); - if (initFilter(filter)) { - filterCaches.insert(std::make_pair(layer->uniqueID, filter)); + LayerStylesFilter* filter = nullptr; + auto result = filterCaches.find(layer->uniqueID); + if (result == filterCaches.end()) { + filter = new LayerStylesFilter(this); + if (initFilter(filter)) { + filterCaches.insert(std::make_pair(layer->uniqueID, filter)); + } else { + delete filter; + filter = nullptr; + } } else { - delete filter; - filter = nullptr; + filter = static_cast(result->second); } - } else { - filter = static_cast(result->second); - } - return filter; + return filter; } void RenderCache::clearFilterCache(ID uniqueID) { - auto result = filterCaches.find(uniqueID); - if (result != filterCaches.end()) { - delete result->second; - filterCaches.erase(result); - } + auto result = filterCaches.find(uniqueID); + if (result != filterCaches.end()) { + delete result->second; + filterCaches.erase(result); + } } void RenderCache::recordImageDecodingTime(int64_t decodingTime) { - imageDecodingTime += decodingTime; + imageDecodingTime += decodingTime; } void RenderCache::recordTextureUploadingTime(int64_t time) { - textureUploadingTime += time; + textureUploadingTime += time; } void RenderCache::recordProgramCompilingTime(int64_t time) { - programCompilingTime += time; + programCompilingTime += time; } } // namespace pag diff --git a/src/rendering/caches/RenderCache.h b/src/rendering/caches/RenderCache.h index 9b1a4a0993..14d2122f9e 100644 --- a/src/rendering/caches/RenderCache.h +++ b/src/rendering/caches/RenderCache.h @@ -35,143 +35,143 @@ namespace pag { class RenderCache : public Performance { - public: - explicit RenderCache(PAGStage* stage); +public: + explicit RenderCache(PAGStage* stage); - ~RenderCache() override; + ~RenderCache() override; - ID uniqueID() const { - return _uniqueID; - } + ID uniqueID() const { + return _uniqueID; + } - void prepareFrame(); + void prepareFrame(); - void attachToContext(Context* current, bool forHitTest = false); + void attachToContext(Context* current, bool forHitTest = false); - void detachFromContext(); + void detachFromContext(); - /** - * Returns the total memory usage of this cache. - */ - size_t memoryUsage() const { - return graphicsMemory; - } + /** + * Returns the total memory usage of this cache. + */ + size_t memoryUsage() const { + return graphicsMemory; + } - /** - * Returns the GPU context associated with this cache. - */ - Context* getContext() const { - return context; - } + /** + * Returns the GPU context associated with this cache. + */ + Context* getContext() const { + return context; + } - /** - * If set to false, the getSnapshot() always returns nullptr. The default value is true. - */ - bool snapshotEnabled() const; + /** + * If set to false, the getSnapshot() always returns nullptr. The default value is true. + */ + bool snapshotEnabled() const; - /** - * Set the value of snapshotEnabled property. - */ - void setSnapshotEnabled(bool value); + /** + * Set the value of snapshotEnabled property. + */ + void setSnapshotEnabled(bool value); - /** - * Returns true if there is snapshot cache available for specified asset ID. - */ - bool hasSnapshot(ID assetID) const { - return snapshotCaches.count(assetID) > 0; - } + /** + * Returns true if there is snapshot cache available for specified asset ID. + */ + bool hasSnapshot(ID assetID) const { + return snapshotCaches.count(assetID) > 0; + } - /** - * Returns a snapshot cache of specified asset id. Returns null if there is no associated cache - * available. This is a read-only query which is used usually during hit testing. - */ - Snapshot* getSnapshot(ID assetID) const; + /** + * Returns a snapshot cache of specified asset id. Returns null if there is no associated cache + * available. This is a read-only query which is used usually during hit testing. + */ + Snapshot* getSnapshot(ID assetID) const; - /** - * Returns a snapshot cache of specified Image. If there is no associated cache available, - * a new cache will be created by the image. Returns null if the image fails to make a - * new snapshot. - */ - Snapshot* getSnapshot(const Picture* image); + /** + * Returns a snapshot cache of specified Image. If there is no associated cache available, + * a new cache will be created by the image. Returns null if the image fails to make a + * new snapshot. + */ + Snapshot* getSnapshot(const Picture* image); - /** - * Frees the snapshot cache associated with specified asset ID immediately. - */ - void removeSnapshot(ID assetID); + /** + * Frees the snapshot cache associated with specified asset ID immediately. + */ + void removeSnapshot(ID assetID); - /** - * Prepares a bitmap task for next getImageBuffer() call. - */ - void prepareImage(ID assetID, std::shared_ptr image); + /** + * Prepares a bitmap task for next getImageBuffer() call. + */ + void prepareImage(ID assetID, std::shared_ptr image); - /** - * Returns a texture buffer cache of specified asset id. Returns null if there is no associated - * cache available. - */ - std::shared_ptr getImageBuffer(ID assetID); + /** + * Returns a texture buffer cache of specified asset id. Returns null if there is no associated + * cache available. + */ + std::shared_ptr getImageBuffer(ID assetID); - uint32_t getContentVersion() const; + uint32_t getContentVersion() const; - bool videoEnabled() const; + bool videoEnabled() const; - void setVideoEnabled(bool value); + void setVideoEnabled(bool value); - bool prepareSequenceReader(Sequence* sequence, Frame targetFrame, DecodingPolicy policy); + bool prepareSequenceReader(Sequence* sequence, Frame targetFrame, DecodingPolicy policy); - std::shared_ptr getSequenceReader(Sequence* sequence); + std::shared_ptr getSequenceReader(Sequence* sequence); - LayerFilter* getFilterCache(LayerStyle* layerStyle); + LayerFilter* getFilterCache(LayerStyle* layerStyle); - LayerFilter* getFilterCache(Effect* effect); + LayerFilter* getFilterCache(Effect* effect); - MotionBlurFilter* getMotionBlurFilter(); + MotionBlurFilter* getMotionBlurFilter(); - LayerStylesFilter* getLayerStylesFilter(Layer* layer); + LayerStylesFilter* getLayerStylesFilter(Layer* layer); - void recordImageDecodingTime(int64_t decodingTime); + void recordImageDecodingTime(int64_t decodingTime); - void recordTextureUploadingTime(int64_t time); + void recordTextureUploadingTime(int64_t time); - void recordProgramCompilingTime(int64_t time); + void recordProgramCompilingTime(int64_t time); - void releaseAll(); + void releaseAll(); - private: - ID _uniqueID = 0; - PAGStage* stage = nullptr; - uint32_t deviceID = 0; - Context* context = nullptr; - int64_t lastTimestamp = 0; - bool hitTestOnly = false; - size_t graphicsMemory = 0; - bool _videoEnabled = true; - bool _snapshotEnabled = true; - std::unordered_set usedAssets = {}; - std::unordered_map snapshotCaches = {}; - std::list snapshotLRU = {}; - std::unordered_map> imageTasks; - std::unordered_map> sequenceCaches; - std::unordered_map filterCaches; - MotionBlurFilter* motionBlurFilter = nullptr; - - // bitmap caches: - void clearExpiredBitmaps(); - - // snapshot caches: - void clearAllSnapshots(); - void clearExpiredSnapshots(); - - // sequence caches: - void clearAllSequenceCaches(); - void clearSequenceCache(ID uniqueID); - void clearExpiredSequences(); - - // filter caches: - LayerFilter* getLayerFilterCache(ID uniqueID, const std::function& makeFilter); - void clearFilterCache(ID uniqueID); - bool initFilter(Filter* filter); +private: + ID _uniqueID = 0; + PAGStage* stage = nullptr; + uint32_t deviceID = 0; + Context* context = nullptr; + int64_t lastTimestamp = 0; + bool hitTestOnly = false; + size_t graphicsMemory = 0; + bool _videoEnabled = true; + bool _snapshotEnabled = true; + std::unordered_set usedAssets = {}; + std::unordered_map snapshotCaches = {}; + std::list snapshotLRU = {}; + std::unordered_map> imageTasks; + std::unordered_map> sequenceCaches; + std::unordered_map filterCaches; + MotionBlurFilter* motionBlurFilter = nullptr; + + // bitmap caches: + void clearExpiredBitmaps(); + + // snapshot caches: + void clearAllSnapshots(); + void clearExpiredSnapshots(); + + // sequence caches: + void clearAllSequenceCaches(); + void clearSequenceCache(ID uniqueID); + void clearExpiredSequences(); + + // filter caches: + LayerFilter* getLayerFilterCache(ID uniqueID, const std::function& makeFilter); + void clearFilterCache(ID uniqueID); + bool initFilter(Filter* filter); - void preparePreComposeLayer(PreComposeLayer* layer, DecodingPolicy policy); - void prepareImageLayer(PAGImageLayer* layer); + void preparePreComposeLayer(PreComposeLayer* layer, DecodingPolicy policy); + void prepareImageLayer(PAGImageLayer* layer); }; } // namespace pag diff --git a/src/rendering/caches/ShapeContentCache.cpp b/src/rendering/caches/ShapeContentCache.cpp index 3410364cff..1951b39052 100644 --- a/src/rendering/caches/ShapeContentCache.cpp +++ b/src/rendering/caches/ShapeContentCache.cpp @@ -24,13 +24,13 @@ ShapeContentCache::ShapeContentCache(ShapeLayer* layer) : ContentCache(layer) { } void ShapeContentCache::excludeVaryingRanges(std::vector* timeRanges) const { - for (auto& element : static_cast(layer)->contents) { - element->excludeVaryingRanges(timeRanges); - } + for (auto& element : static_cast(layer)->contents) { + element->excludeVaryingRanges(timeRanges); + } } GraphicContent* ShapeContentCache::createContent(Frame layerFrame) const { - auto graphic = RenderShapes(static_cast(layer)->contents, layerFrame); - return new GraphicContent(graphic); + auto graphic = RenderShapes(static_cast(layer)->contents, layerFrame); + return new GraphicContent(graphic); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/ShapeContentCache.h b/src/rendering/caches/ShapeContentCache.h index 6b3a504644..a8b3f2f18a 100644 --- a/src/rendering/caches/ShapeContentCache.h +++ b/src/rendering/caches/ShapeContentCache.h @@ -22,11 +22,11 @@ namespace pag { class ShapeContentCache : public ContentCache { - public: - explicit ShapeContentCache(ShapeLayer* layer); +public: + explicit ShapeContentCache(ShapeLayer* layer); - protected: - void excludeVaryingRanges(std::vector* timeRanges) const override; - GraphicContent* createContent(Frame layerFrame) const override; +protected: + void excludeVaryingRanges(std::vector* timeRanges) const override; + GraphicContent* createContent(Frame layerFrame) const override; }; } // namespace pag diff --git a/src/rendering/caches/SolidContentCache.cpp b/src/rendering/caches/SolidContentCache.cpp index 738f1979f8..3b47fb0fad 100644 --- a/src/rendering/caches/SolidContentCache.cpp +++ b/src/rendering/caches/SolidContentCache.cpp @@ -24,10 +24,10 @@ SolidContentCache::SolidContentCache(SolidLayer* layer) : ContentCache(layer) { } GraphicContent* SolidContentCache::createContent(Frame) const { - auto solidLayer = static_cast(layer); - Path path = {}; - path.addRect(0, 0, solidLayer->width, solidLayer->height); - auto graphic = Shape::MakeFrom(path, solidLayer->solidColor); - return new GraphicContent(graphic); + auto solidLayer = static_cast(layer); + Path path = {}; + path.addRect(0, 0, solidLayer->width, solidLayer->height); + auto graphic = Shape::MakeFrom(path, solidLayer->solidColor); + return new GraphicContent(graphic); } } // namespace pag diff --git a/src/rendering/caches/SolidContentCache.h b/src/rendering/caches/SolidContentCache.h index f60525c2ec..82168b9f51 100644 --- a/src/rendering/caches/SolidContentCache.h +++ b/src/rendering/caches/SolidContentCache.h @@ -22,10 +22,10 @@ namespace pag { class SolidContentCache : public ContentCache { - public: - explicit SolidContentCache(SolidLayer* layer); +public: + explicit SolidContentCache(SolidLayer* layer); - protected: - GraphicContent* createContent(Frame layerFrame) const override; +protected: + GraphicContent* createContent(Frame layerFrame) const override; }; } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/TextContent.h b/src/rendering/caches/TextContent.h index 406974905c..f89e2544b0 100644 --- a/src/rendering/caches/TextContent.h +++ b/src/rendering/caches/TextContent.h @@ -22,11 +22,11 @@ namespace pag { class TextContent : public GraphicContent { - public: - TextContent(std::shared_ptr graphic, std::shared_ptr colorGlyphs) - : GraphicContent(std::move(graphic)), colorGlyphs(std::move(colorGlyphs)) { - } +public: + TextContent(std::shared_ptr graphic, std::shared_ptr colorGlyphs) + : GraphicContent(std::move(graphic)), colorGlyphs(std::move(colorGlyphs)) { + } - std::shared_ptr colorGlyphs = nullptr; + std::shared_ptr colorGlyphs = nullptr; }; } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/TextContentCache.cpp b/src/rendering/caches/TextContentCache.cpp index 3c2abbcdf0..13f1093b5d 100644 --- a/src/rendering/caches/TextContentCache.cpp +++ b/src/rendering/caches/TextContentCache.cpp @@ -40,28 +40,28 @@ TextContentCache::TextContentCache(TextLayer* layer, ID cacheID, } void TextContentCache::excludeVaryingRanges(std::vector* timeRanges) const { - sourceText->excludeVaryingRanges(timeRanges); - if (pathOption) { - pathOption->excludeVaryingRanges(timeRanges); - } - if (moreOption) { - moreOption->excludeVaryingRanges(timeRanges); - } - for (auto animator : *animators) { - animator->excludeVaryingRanges(timeRanges); - } + sourceText->excludeVaryingRanges(timeRanges); + if (pathOption) { + pathOption->excludeVaryingRanges(timeRanges); + } + if (moreOption) { + moreOption->excludeVaryingRanges(timeRanges); + } + for (auto animator : *animators) { + animator->excludeVaryingRanges(timeRanges); + } } ID TextContentCache::getCacheID() const { - return cacheID > 0 ? cacheID : layer->uniqueID; + return cacheID > 0 ? cacheID : layer->uniqueID; } GraphicContent* TextContentCache::createContent(Frame layerFrame) const { - auto content = RenderTexts(sourceText, pathOption, moreOption, animators, layerFrame).release(); - if (_cacheEnabled) { - content->colorGlyphs = Picture::MakeFrom(getCacheID(), content->colorGlyphs); - } - return content; + auto content = RenderTexts(sourceText, pathOption, moreOption, animators, layerFrame).release(); + if (_cacheEnabled) { + content->colorGlyphs = Picture::MakeFrom(getCacheID(), content->colorGlyphs); + } + return content; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/TextContentCache.h b/src/rendering/caches/TextContentCache.h index 6e16d07509..fe5871f956 100644 --- a/src/rendering/caches/TextContentCache.h +++ b/src/rendering/caches/TextContentCache.h @@ -22,20 +22,20 @@ namespace pag { class TextContentCache : public ContentCache { - public: - explicit TextContentCache(TextLayer* layer); - TextContentCache(TextLayer* layer, ID cacheID, Property* sourceText); +public: + explicit TextContentCache(TextLayer* layer); + TextContentCache(TextLayer* layer, ID cacheID, Property* sourceText); - protected: - void excludeVaryingRanges(std::vector* timeRanges) const override; - ID getCacheID() const override; - GraphicContent* createContent(Frame layerFrame) const override; +protected: + void excludeVaryingRanges(std::vector* timeRanges) const override; + ID getCacheID() const override; + GraphicContent* createContent(Frame layerFrame) const override; - private: - ID cacheID = 0; - Property* sourceText; - TextPathOptions* pathOption; - TextMoreOptions* moreOption; - std::vector* animators; +private: + ID cacheID = 0; + Property* sourceText; + TextPathOptions* pathOption; + TextMoreOptions* moreOption; + std::vector* animators; }; } // namespace pag diff --git a/src/rendering/caches/TransformCache.cpp b/src/rendering/caches/TransformCache.cpp index 356c056565..9cb93c2ea0 100644 --- a/src/rendering/caches/TransformCache.cpp +++ b/src/rendering/caches/TransformCache.cpp @@ -22,28 +22,28 @@ namespace pag { TransformCache::TransformCache(Layer* layer) : FrameCache(layer->startTime, layer->duration), layer(layer) { - std::vector timeRanges = {layer->visibleRange()}; - layer->transform->excludeVaryingRanges(&timeRanges); - auto parent = layer->parent; - while (parent != nullptr) { - parent->transform->excludeVaryingRanges(&timeRanges); - SplitTimeRangesAt(&timeRanges, parent->startTime); - SplitTimeRangesAt(&timeRanges, parent->startTime + parent->duration); - parent = parent->parent; - } - staticTimeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); + std::vector timeRanges = {layer->visibleRange()}; + layer->transform->excludeVaryingRanges(&timeRanges); + auto parent = layer->parent; + while (parent != nullptr) { + parent->transform->excludeVaryingRanges(&timeRanges); + SplitTimeRangesAt(&timeRanges, parent->startTime); + SplitTimeRangesAt(&timeRanges, parent->startTime + parent->duration); + parent = parent->parent; + } + staticTimeRanges = OffsetTimeRanges(timeRanges, -layer->startTime); } Transform* TransformCache::createCache(Frame layerFrame) { - auto transform = new Transform(); - RenderTransform(transform, layer->transform, layerFrame); - auto parent = layer->parent; - while (parent != nullptr) { - Transform parentTransform = {}; - RenderTransform(&parentTransform, parent->transform, layerFrame); - transform->matrix.postConcat(parentTransform.matrix); - parent = parent->parent; - } - return transform; + auto transform = new Transform(); + RenderTransform(transform, layer->transform, layerFrame); + auto parent = layer->parent; + while (parent != nullptr) { + Transform parentTransform = {}; + RenderTransform(&parentTransform, parent->transform, layerFrame); + transform->matrix.postConcat(parentTransform.matrix); + parent = parent->parent; + } + return transform; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/caches/TransformCache.h b/src/rendering/caches/TransformCache.h index 5b3b32be47..db8344e044 100644 --- a/src/rendering/caches/TransformCache.h +++ b/src/rendering/caches/TransformCache.h @@ -23,13 +23,13 @@ namespace pag { class TransformCache : public FrameCache { - public: - explicit TransformCache(Layer* layer); +public: + explicit TransformCache(Layer* layer); - protected: - Transform* createCache(Frame layerFrame) override; +protected: + Transform* createCache(Frame layerFrame) override; - private: - Layer* layer = nullptr; +private: + Layer* layer = nullptr; }; } // namespace pag diff --git a/src/rendering/editing/ImageReplacement.cpp b/src/rendering/editing/ImageReplacement.cpp index df72671e86..a6e0639833 100644 --- a/src/rendering/editing/ImageReplacement.cpp +++ b/src/rendering/editing/ImageReplacement.cpp @@ -26,38 +26,38 @@ namespace pag { ImageReplacement::ImageReplacement(ImageLayer* imageLayer, PAGImageHolder* imageHolder, int editableIndex) : imageHolder(imageHolder), editableIndex(editableIndex) { - auto imageFillRule = imageLayer->imageFillRule; - defaultScaleMode = imageFillRule ? imageFillRule->scaleMode : PAGScaleMode::LetterBox; - contentWidth = imageLayer->imageBytes->width; - contentHeight = imageLayer->imageBytes->height; + auto imageFillRule = imageLayer->imageFillRule; + defaultScaleMode = imageFillRule ? imageFillRule->scaleMode : PAGScaleMode::LetterBox; + contentWidth = imageLayer->imageBytes->width; + contentHeight = imageLayer->imageBytes->height; } void ImageReplacement::measureBounds(Rect* bounds) { - Rect contentBounds = {}; - auto pagImage = imageHolder->getImage(editableIndex); - pagImage->measureBounds(&contentBounds); - auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); - contentMatrix.mapRect(&contentBounds); - bounds->setXYWH(0, 0, contentWidth, contentHeight); - if (!bounds->intersect(contentBounds)) { - bounds->setEmpty(); - } + Rect contentBounds = {}; + auto pagImage = imageHolder->getImage(editableIndex); + pagImage->measureBounds(&contentBounds); + auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); + contentMatrix.mapRect(&contentBounds); + bounds->setXYWH(0, 0, contentWidth, contentHeight); + if (!bounds->intersect(contentBounds)) { + bounds->setEmpty(); + } } void ImageReplacement::draw(Recorder* recorder) { - recorder->saveClip(0, 0, static_cast(contentWidth), static_cast(contentHeight)); - auto pagImage = imageHolder->getImage(editableIndex); - auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); - recorder->concat(contentMatrix); - pagImage->draw(recorder); - recorder->restore(); + recorder->saveClip(0, 0, static_cast(contentWidth), static_cast(contentHeight)); + auto pagImage = imageHolder->getImage(editableIndex); + auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); + recorder->concat(contentMatrix); + pagImage->draw(recorder); + recorder->restore(); } Point ImageReplacement::getScaleFactor() const { - // TODO((domrjchen): - // 当PAGImage的适配模式或者matrix发生改变时,需要补充一个通知机制让上层重置scaleFactor。 - auto pagImage = imageHolder->getImage(editableIndex); - auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); - return GetScaleFactor(contentMatrix); + // TODO((domrjchen): + // 当PAGImage的适配模式或者matrix发生改变时,需要补充一个通知机制让上层重置scaleFactor。 + auto pagImage = imageHolder->getImage(editableIndex); + auto contentMatrix = pagImage->getContentMatrix(defaultScaleMode, contentWidth, contentHeight); + return GetScaleFactor(contentMatrix); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/editing/ImageReplacement.h b/src/rendering/editing/ImageReplacement.h index 32986eff7f..4cd2de1858 100644 --- a/src/rendering/editing/ImageReplacement.h +++ b/src/rendering/editing/ImageReplacement.h @@ -21,18 +21,18 @@ namespace pag { class ImageReplacement : public Content { - public: - ImageReplacement(ImageLayer* imageLayer, PAGImageHolder* imageHolder, int editableIndex); +public: + ImageReplacement(ImageLayer* imageLayer, PAGImageHolder* imageHolder, int editableIndex); - void measureBounds(Rect* bounds) override; - void draw(Recorder* recorder) override; - Point getScaleFactor() const; + void measureBounds(Rect* bounds) override; + void draw(Recorder* recorder) override; + Point getScaleFactor() const; - private: - PAGImageHolder* imageHolder = nullptr; - int editableIndex = 0; - int defaultScaleMode = PAGScaleMode::LetterBox; - int contentWidth = 0; - int contentHeight = 0; +private: + PAGImageHolder* imageHolder = nullptr; + int editableIndex = 0; + int defaultScaleMode = PAGScaleMode::LetterBox; + int contentWidth = 0; + int contentHeight = 0; }; } // namespace pag diff --git a/src/rendering/editing/PAGImage.cpp b/src/rendering/editing/PAGImage.cpp index d196bf867d..8a4abe9e16 100644 --- a/src/rendering/editing/PAGImage.cpp +++ b/src/rendering/editing/PAGImage.cpp @@ -27,50 +27,50 @@ PAGImage::PAGImage() : _uniqueID(UniqueID::Next()) { } ID PAGImage::uniqueID() const { - return _uniqueID; + return _uniqueID; } int PAGImage::width() { - return static_cast(getContentSize().width()); + return static_cast(getContentSize().width()); } int PAGImage::height() { - return static_cast(getContentSize().height()); + return static_cast(getContentSize().height()); } int PAGImage::scaleMode() { - std::lock_guard autoLock(locker); - return _scaleMode; + std::lock_guard autoLock(locker); + return _scaleMode; } void PAGImage::setScaleMode(int mode) { - std::lock_guard autoLock(locker); - _scaleMode = mode; - _matrix.setIdentity(); - hasSetScaleMode = true; + std::lock_guard autoLock(locker); + _scaleMode = mode; + _matrix.setIdentity(); + hasSetScaleMode = true; } Matrix PAGImage::matrix() { - std::lock_guard autoLock(locker); - return _matrix; + std::lock_guard autoLock(locker); + return _matrix; } void PAGImage::setMatrix(const Matrix& matrix) { - std::lock_guard autoLock(locker); - _scaleMode = PAGScaleMode::None; - _matrix = matrix; - hasSetScaleMode = true; + std::lock_guard autoLock(locker); + _scaleMode = PAGScaleMode::None; + _matrix = matrix; + hasSetScaleMode = true; } Matrix PAGImage::getContentMatrix(int defaultScaleMode, int contentWidth, int contentHeight) { - auto scaleMode = hasSetScaleMode ? _scaleMode : defaultScaleMode; - Matrix matrix = {}; - if (scaleMode != PAGScaleMode::None) { - auto size = getContentSize(); - matrix = ApplyScaleMode(scaleMode, size.width(), size.height(), contentWidth, contentHeight); - } else { - matrix = _matrix; - } - return matrix; + auto scaleMode = hasSetScaleMode ? _scaleMode : defaultScaleMode; + Matrix matrix = {}; + if (scaleMode != PAGScaleMode::None) { + auto size = getContentSize(); + matrix = ApplyScaleMode(scaleMode, size.width(), size.height(), contentWidth, contentHeight); + } else { + matrix = _matrix; + } + return matrix; } } // namespace pag diff --git a/src/rendering/editing/PAGImageHolder.cpp b/src/rendering/editing/PAGImageHolder.cpp index c151a7d16b..39e55d60a3 100644 --- a/src/rendering/editing/PAGImageHolder.cpp +++ b/src/rendering/editing/PAGImageHolder.cpp @@ -20,46 +20,46 @@ namespace pag { bool PAGImageHolder::hasImage(int editableIndex) const { - return imageMap.count(editableIndex) > 0; + return imageMap.count(editableIndex) > 0; } std::shared_ptr PAGImageHolder::getImage(int editableIndex) const { - auto result = imageMap.find(editableIndex); - if (result != imageMap.end()) { - return result->second; - } - return nullptr; + auto result = imageMap.find(editableIndex); + if (result != imageMap.end()) { + return result->second; + } + return nullptr; } void PAGImageHolder::setImage(int editableIndex, std::shared_ptr image) { - if (image) { - imageMap[editableIndex] = image; - } else { - imageMap.erase(editableIndex); - } + if (image) { + imageMap[editableIndex] = image; + } else { + imageMap.erase(editableIndex); + } } void PAGImageHolder::addLayer(PAGLayer* layer) { - auto position = std::find(imageLayers.begin(), imageLayers.end(), layer); - if (position == imageLayers.end()) { - imageLayers.push_back(layer); - } + auto position = std::find(imageLayers.begin(), imageLayers.end(), layer); + if (position == imageLayers.end()) { + imageLayers.push_back(layer); + } } void PAGImageHolder::removeLayer(PAGLayer* layer) { - auto position = std::find(imageLayers.begin(), imageLayers.end(), layer); - if (position != imageLayers.end()) { - imageLayers.erase(position); - } + auto position = std::find(imageLayers.begin(), imageLayers.end(), layer); + if (position != imageLayers.end()) { + imageLayers.erase(position); + } } std::vector PAGImageHolder::getLayers(int editableIndex) { - std::vector layers = {}; - for (auto& layer : imageLayers) { - if (layer->editableIndex() == editableIndex) { - layers.push_back(layer); + std::vector layers = {}; + for (auto& layer : imageLayers) { + if (layer->editableIndex() == editableIndex) { + layers.push_back(layer); + } } - } - return layers; + return layers; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/editing/PAGImageHolder.h b/src/rendering/editing/PAGImageHolder.h index c769f00479..cb71bdcf75 100644 --- a/src/rendering/editing/PAGImageHolder.h +++ b/src/rendering/editing/PAGImageHolder.h @@ -23,21 +23,21 @@ namespace pag { class PAGImageHolder { - public: - bool hasImage(int editableIndex) const; +public: + bool hasImage(int editableIndex) const; - std::shared_ptr getImage(int editableIndex) const; + std::shared_ptr getImage(int editableIndex) const; - void setImage(int editableIndex, std::shared_ptr image); + void setImage(int editableIndex, std::shared_ptr image); - void addLayer(PAGLayer* layer); + void addLayer(PAGLayer* layer); - void removeLayer(PAGLayer* layer); + void removeLayer(PAGLayer* layer); - std::vector getLayers(int editableIndex); + std::vector getLayers(int editableIndex); - private: - std::unordered_map> imageMap; - std::vector imageLayers; +private: + std::unordered_map> imageMap; + std::vector imageLayers; }; } // namespace pag diff --git a/src/rendering/editing/StillImage.cpp b/src/rendering/editing/StillImage.cpp index efbbbf08e2..614757d174 100644 --- a/src/rendering/editing/StillImage.cpp +++ b/src/rendering/editing/StillImage.cpp @@ -28,103 +28,103 @@ namespace pag { std::shared_ptr PAGImage::FromPath(const std::string& filePath) { - auto pagImage = std::make_shared(); - pagImage->image = Image::MakeFrom(filePath); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); - if (!picture) { - return nullptr; - } - pagImage->reset(picture); - return pagImage; + auto pagImage = std::make_shared(); + pagImage->image = Image::MakeFrom(filePath); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); + if (!picture) { + return nullptr; + } + pagImage->reset(picture); + return pagImage; } std::shared_ptr PAGImage::FromBytes(const void* bytes, size_t length) { - auto pagImage = std::make_shared(); - auto fileBytes = Data::MakeWithCopy(bytes, length); - pagImage->image = Image::MakeFrom(std::move(fileBytes)); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); - if (!picture) { - return nullptr; - } - pagImage->reset(picture); - return pagImage; + auto pagImage = std::make_shared(); + auto fileBytes = Data::MakeWithCopy(bytes, length); + pagImage->image = Image::MakeFrom(std::move(fileBytes)); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); + if (!picture) { + return nullptr; + } + pagImage->reset(picture); + return pagImage; } std::shared_ptr PAGImage::FromPixels(const void* pixels, int width, int height, - size_t rowBytes, ColorType colorType, - AlphaType alphaType) { - Bitmap bitmap = {}; - if (!bitmap.allocPixels(width, height)) { - return nullptr; - } - auto info = ImageInfo::Make(width, height, colorType, alphaType, rowBytes); - auto result = bitmap.writePixels(info, pixels); - if (!result) { - return nullptr; - } - return StillImage::FromBitmap(bitmap); + size_t rowBytes, ColorType colorType, + AlphaType alphaType) { + Bitmap bitmap = {}; + if (!bitmap.allocPixels(width, height)) { + return nullptr; + } + auto info = ImageInfo::Make(width, height, colorType, alphaType, rowBytes); + auto result = bitmap.writePixels(info, pixels); + if (!result) { + return nullptr; + } + return StillImage::FromBitmap(bitmap); } std::shared_ptr StillImage::FromBitmap(const Bitmap& bitmap) { - if (bitmap.isEmpty()) { - return nullptr; - } - auto pagImage = std::make_shared(); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), bitmap); - if (!picture) { - return nullptr; - } - pagImage->reset(picture); - return pagImage; + if (bitmap.isEmpty()) { + return nullptr; + } + auto pagImage = std::make_shared(); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), bitmap); + if (!picture) { + return nullptr; + } + pagImage->reset(picture); + return pagImage; } std::shared_ptr StillImage::FromImage(std::shared_ptr image) { - if (image == nullptr) { - return nullptr; - } - auto pagImage = std::make_shared(); - pagImage->image = std::move(image); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); - if (!picture) { - return nullptr; - } - pagImage->reset(picture); - return pagImage; + if (image == nullptr) { + return nullptr; + } + auto pagImage = std::make_shared(); + pagImage->image = std::move(image); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), pagImage->image); + if (!picture) { + return nullptr; + } + pagImage->reset(picture); + return pagImage; } std::shared_ptr PAGImage::FromTexture(const BackendTexture& texture, ImageOrigin origin) { - auto context = NativeGLDevice::GetCurrentNativeHandle(); - if (context == nullptr) { - LOGE("PAGImage.MakeFrom() There is no current GPU context on the calling thread."); - return nullptr; - } - auto pagImage = std::make_shared(); - auto picture = Picture::MakeFrom(pagImage->uniqueID(), texture, origin); - if (!picture) { - LOGE("PAGImage.MakeFrom() The texture is invalid."); - return nullptr; - } - pagImage->reset(picture); - return pagImage; + auto context = NativeGLDevice::GetCurrentNativeHandle(); + if (context == nullptr) { + LOGE("PAGImage.MakeFrom() There is no current GPU context on the calling thread."); + return nullptr; + } + auto pagImage = std::make_shared(); + auto picture = Picture::MakeFrom(pagImage->uniqueID(), texture, origin); + if (!picture) { + LOGE("PAGImage.MakeFrom() The texture is invalid."); + return nullptr; + } + pagImage->reset(picture); + return pagImage; } void StillImage::measureBounds(Rect* bounds) { - graphic->measureBounds(bounds); + graphic->measureBounds(bounds); } Rect StillImage::getContentSize() const { - return Rect::MakeWH(static_cast(width), static_cast(height)); + return Rect::MakeWH(static_cast(width), static_cast(height)); } void StillImage::draw(Recorder* recorder) { - recorder->drawGraphic(graphic); + recorder->drawGraphic(graphic); } void StillImage::reset(std::shared_ptr g) { - Rect bounds = {}; - g->measureBounds(&bounds); - width = static_cast(bounds.width()); - height = static_cast(bounds.height()); - graphic = g; + Rect bounds = {}; + g->measureBounds(&bounds); + width = static_cast(bounds.width()); + height = static_cast(bounds.height()); + graphic = g; } } // namespace pag diff --git a/src/rendering/editing/StillImage.h b/src/rendering/editing/StillImage.h index 5d4f563e3a..fa94b2e135 100644 --- a/src/rendering/editing/StillImage.h +++ b/src/rendering/editing/StillImage.h @@ -24,28 +24,28 @@ namespace pag { class StillImage : public PAGImage { - public: - static std::shared_ptr FromBitmap(const Bitmap& bitmap); - static std::shared_ptr FromImage(std::shared_ptr image); +public: + static std::shared_ptr FromBitmap(const Bitmap& bitmap); + static std::shared_ptr FromImage(std::shared_ptr image); - void measureBounds(Rect* bounds) override; - void draw(Recorder* recorder) override; + void measureBounds(Rect* bounds) override; + void draw(Recorder* recorder) override; - protected: - Rect getContentSize() const override; +protected: + Rect getContentSize() const override; - std::shared_ptr getImage() const override { - return image; - } + std::shared_ptr getImage() const override { + return image; + } - private: - int width = 0; - int height = 0; - std::shared_ptr image = nullptr; - std::shared_ptr graphic = nullptr; +private: + int width = 0; + int height = 0; + std::shared_ptr image = nullptr; + std::shared_ptr graphic = nullptr; - void reset(std::shared_ptr graphic); + void reset(std::shared_ptr graphic); - friend class PAGImage; + friend class PAGImage; }; } // namespace pag diff --git a/src/rendering/editing/TextReplacement.cpp b/src/rendering/editing/TextReplacement.cpp index 4853c6b885..2beb71fc9f 100644 --- a/src/rendering/editing/TextReplacement.cpp +++ b/src/rendering/editing/TextReplacement.cpp @@ -20,35 +20,35 @@ namespace pag { TextReplacement::TextReplacement(PAGTextLayer* pagLayer) : pagLayer(pagLayer) { - auto textLayer = static_cast(pagLayer->layer); - sourceText = new Property(); - auto textData = TextDocumentHandle(new TextDocument()); - *textData = *(textLayer->sourceText->value); - sourceText->value = textData; - textContentCache = new TextContentCache(textLayer, pagLayer->uniqueID(), sourceText); - textContentCache->update(); + auto textLayer = static_cast(pagLayer->layer); + sourceText = new Property(); + auto textData = TextDocumentHandle(new TextDocument()); + *textData = *(textLayer->sourceText->value); + sourceText->value = textData; + textContentCache = new TextContentCache(textLayer, pagLayer->uniqueID(), sourceText); + textContentCache->update(); } TextReplacement::~TextReplacement() { - delete textContentCache; - delete sourceText; + delete textContentCache; + delete sourceText; } Content* TextReplacement::getContent(Frame contentFrame) { - if (textContentCache == nullptr) { - auto textLayer = static_cast(pagLayer->layer); - textContentCache = new TextContentCache(textLayer, pagLayer->uniqueID(), sourceText); - textContentCache->update(); - } - return textContentCache->getCache(contentFrame); + if (textContentCache == nullptr) { + auto textLayer = static_cast(pagLayer->layer); + textContentCache = new TextContentCache(textLayer, pagLayer->uniqueID(), sourceText); + textContentCache->update(); + } + return textContentCache->getCache(contentFrame); } TextDocument* TextReplacement::getTextDocument() { - return sourceText->value.get(); + return sourceText->value.get(); } void TextReplacement::clearCache() { - delete textContentCache; - textContentCache = nullptr; + delete textContentCache; + textContentCache = nullptr; } } // namespace pag diff --git a/src/rendering/editing/TextReplacement.h b/src/rendering/editing/TextReplacement.h index 3095f910fd..cdcd24f6f9 100644 --- a/src/rendering/editing/TextReplacement.h +++ b/src/rendering/editing/TextReplacement.h @@ -22,19 +22,19 @@ namespace pag { class TextReplacement { - public: - explicit TextReplacement(PAGTextLayer* textLayer); - ~TextReplacement(); +public: + explicit TextReplacement(PAGTextLayer* textLayer); + ~TextReplacement(); - Content* getContent(Frame contentFrame); + Content* getContent(Frame contentFrame); - TextDocument* getTextDocument(); + TextDocument* getTextDocument(); - void clearCache(); + void clearCache(); - private: - TextContentCache* textContentCache = nullptr; - Property* sourceText = nullptr; - PAGTextLayer* pagLayer = nullptr; +private: + TextContentCache* textContentCache = nullptr; + Property* sourceText = nullptr; + PAGTextLayer* pagLayer = nullptr; }; } // namespace pag diff --git a/src/rendering/filters/BulgeFilter.cpp b/src/rendering/filters/BulgeFilter.cpp index 6eaadd76c6..76842d7d83 100644 --- a/src/rendering/filters/BulgeFilter.cpp +++ b/src/rendering/filters/BulgeFilter.cpp @@ -83,39 +83,39 @@ BulgeFilter::BulgeFilter(Effect* effect) : effect(effect) { } std::string BulgeFilter::onBuildVertexShader() { - return BULGE_VERTEX_SHADER; + return BULGE_VERTEX_SHADER; } std::string BulgeFilter::onBuildFragmentShader() { - return BULGE_FRAGMENT_SHADER; + return BULGE_FRAGMENT_SHADER; } void BulgeFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - horizontalRadiusHandle = gl->getUniformLocation(program, "uHorizontalRadius"); - verticalRadiusHandle = gl->getUniformLocation(program, "uVerticalRadius"); - bulgeCenterHandle = gl->getUniformLocation(program, "uBulgeCenter"); - bulgeHeightHandle = gl->getUniformLocation(program, "uBulgeHeight"); - pinningHandle = gl->getUniformLocation(program, "uPinning"); + horizontalRadiusHandle = gl->getUniformLocation(program, "uHorizontalRadius"); + verticalRadiusHandle = gl->getUniformLocation(program, "uVerticalRadius"); + bulgeCenterHandle = gl->getUniformLocation(program, "uBulgeCenter"); + bulgeHeightHandle = gl->getUniformLocation(program, "uBulgeHeight"); + pinningHandle = gl->getUniformLocation(program, "uPinning"); } void BulgeFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, const Point&) { - auto* bulgeEffect = reinterpret_cast(effect); - auto horizontalRadius = bulgeEffect->horizontalRadius->getValueAt(layerFrame); - auto verticalRadius = bulgeEffect->verticalRadius->getValueAt(layerFrame); - auto bulgeCenter = bulgeEffect->bulgeCenter->getValueAt(layerFrame); - auto bulgeHeight = bulgeEffect->bulgeHeight->getValueAt(layerFrame); - auto pinning = bulgeEffect->pinning->getValueAt(layerFrame); - - gl->uniform1f(horizontalRadiusHandle, horizontalRadius / contentBounds.width()); - gl->uniform1f(verticalRadiusHandle, verticalRadius / contentBounds.height()); - gl->uniform2f(bulgeCenterHandle, (bulgeCenter.x - contentBounds.x()) / contentBounds.width(), - 1.0f - (bulgeCenter.y - contentBounds.y()) / contentBounds.height()); - gl->uniform1f(bulgeHeightHandle, bulgeHeight); - gl->uniform1i(pinningHandle, pinning); + auto* bulgeEffect = reinterpret_cast(effect); + auto horizontalRadius = bulgeEffect->horizontalRadius->getValueAt(layerFrame); + auto verticalRadius = bulgeEffect->verticalRadius->getValueAt(layerFrame); + auto bulgeCenter = bulgeEffect->bulgeCenter->getValueAt(layerFrame); + auto bulgeHeight = bulgeEffect->bulgeHeight->getValueAt(layerFrame); + auto pinning = bulgeEffect->pinning->getValueAt(layerFrame); + + gl->uniform1f(horizontalRadiusHandle, horizontalRadius / contentBounds.width()); + gl->uniform1f(verticalRadiusHandle, verticalRadius / contentBounds.height()); + gl->uniform2f(bulgeCenterHandle, (bulgeCenter.x - contentBounds.x()) / contentBounds.width(), + 1.0f - (bulgeCenter.y - contentBounds.y()) / contentBounds.height()); + gl->uniform1f(bulgeHeightHandle, bulgeHeight); + gl->uniform1i(pinningHandle, pinning); } std::vector BulgeFilter::computeVertices(const Rect& inputBounds, const Rect& outputBounds, - const Point&) { - return ComputeVerticesForMotionBlurAndBulge(inputBounds, outputBounds); + const Point&) { + return ComputeVerticesForMotionBlurAndBulge(inputBounds, outputBounds); } } // namespace pag diff --git a/src/rendering/filters/BulgeFilter.h b/src/rendering/filters/BulgeFilter.h index 13070e6d83..212a8fb0d4 100644 --- a/src/rendering/filters/BulgeFilter.h +++ b/src/rendering/filters/BulgeFilter.h @@ -22,30 +22,30 @@ namespace pag { class BulgeFilter : public LayerFilter { - public: - explicit BulgeFilter(Effect* effect); - ~BulgeFilter() override = default; +public: + explicit BulgeFilter(Effect* effect); + ~BulgeFilter() override = default; - protected: - std::string onBuildVertexShader() override; +protected: + std::string onBuildVertexShader() override; - std::string onBuildFragmentShader() override; + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - int horizontalRadiusHandle = -1; - int verticalRadiusHandle = -1; - int bulgeCenterHandle = -1; - int bulgeHeightHandle = -1; - int pinningHandle = -1; + int horizontalRadiusHandle = -1; + int verticalRadiusHandle = -1; + int bulgeCenterHandle = -1; + int bulgeHeightHandle = -1; + int pinningHandle = -1; }; } // namespace pag diff --git a/src/rendering/filters/CornerPinFilter.cpp b/src/rendering/filters/CornerPinFilter.cpp index 167664bae6..a3f22fdeaa 100644 --- a/src/rendering/filters/CornerPinFilter.cpp +++ b/src/rendering/filters/CornerPinFilter.cpp @@ -49,108 +49,110 @@ CornerPinFilter::CornerPinFilter(Effect* effect) : effect(effect) { } std::string CornerPinFilter::onBuildVertexShader() { - return CORNER_PIN_VERTEX_SHADER; + return CORNER_PIN_VERTEX_SHADER; } std::string CornerPinFilter::onBuildFragmentShader() { - return CORNER_PIN_FRAGMENT_SHADER; + return CORNER_PIN_FRAGMENT_SHADER; } static float calculateDistance(const Point& intersection, const Point& vertexPoint) { - return std::sqrt(std::pow(fabs(intersection.x - vertexPoint.x), 2) + - std::pow(fabs(intersection.y - vertexPoint.y), 2)); + return std::sqrt(std::pow(fabs(intersection.x - vertexPoint.x), 2) + + std::pow(fabs(intersection.y - vertexPoint.y), 2)); } static bool PointIsBetween(const Point& point, const Point& start, const Point& end) { - auto minX = std::min(start.x, end.x); - auto maxX = std::max(start.x, end.x); - auto minY = std::min(start.y, end.y); - auto maxY = std::max(start.y, end.y); - return minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY; + auto minX = std::min(start.x, end.x); + auto maxX = std::max(start.x, end.x); + auto minY = std::min(start.y, end.y); + auto maxY = std::max(start.y, end.y); + return minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY; } void CornerPinFilter::calculateVertexQs() { - // https://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/ - // 计算2条对角线的交点:y1 = k1 * x1 + b1; y2 = k2 * x2 + b2 - auto* cornerPinEffect = reinterpret_cast(effect); - auto lowerLeft = cornerPinEffect->lowerLeft->getValueAt(layerFrame); - auto upperRight = cornerPinEffect->upperRight->getValueAt(layerFrame); - auto lowerRight = cornerPinEffect->lowerRight->getValueAt(layerFrame); - auto upperLeft = cornerPinEffect->upperLeft->getValueAt(layerFrame); - auto ll2ur_k = (upperRight.y - lowerLeft.y) / (upperRight.x - lowerLeft.x); - auto ul2lr_k = (lowerRight.y - upperLeft.y) / (lowerRight.x - upperLeft.x); - auto ll2ur_b = lowerLeft.y - ll2ur_k * lowerLeft.x; - auto ul2lr_b = upperLeft.y - ul2lr_k * upperLeft.x; - Point intersection = {0, 0}; - intersection.x = (ul2lr_b - ll2ur_b) / (ll2ur_k - ul2lr_k); - intersection.y = ll2ur_k * intersection.x + ll2ur_b; - // 计算对角线交点与4个顶点的距离 - auto lowerLeftDistance = calculateDistance(intersection, lowerLeft); - auto lowerRightDistance = calculateDistance(intersection, lowerRight); - auto upperRightDistance = calculateDistance(intersection, upperRight); - auto upperLeftDistance = calculateDistance(intersection, upperLeft); - // 计算4个顶点的uvq: uvq0 = float3(u0, v0, 1) * (d0 + d2) / d2 - if (PointIsBetween(intersection, lowerLeft, upperRight) && - PointIsBetween(intersection, upperLeft, lowerRight) && upperRightDistance != 0 && - upperLeftDistance != 0 && lowerRightDistance != 0 && lowerLeftDistance != 0) { - vertexQs[0] = (lowerLeftDistance + upperRightDistance) / upperRightDistance; // LowerLeft - vertexQs[1] = (lowerRightDistance + upperLeftDistance) / upperLeftDistance; // LowerRight - vertexQs[2] = (upperLeftDistance + lowerRightDistance) / lowerRightDistance; // UpperLeft - vertexQs[3] = (upperRightDistance + lowerLeftDistance) / lowerLeftDistance; // UpperRight - } else { - vertexQs[0] = 1.0f; - vertexQs[1] = 1.0f; - vertexQs[2] = 1.0f; - vertexQs[3] = 1.0f; - } + // https://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/ + // 计算2条对角线的交点:y1 = k1 * x1 + b1; y2 = k2 * x2 + b2 + auto* cornerPinEffect = reinterpret_cast(effect); + auto lowerLeft = cornerPinEffect->lowerLeft->getValueAt(layerFrame); + auto upperRight = cornerPinEffect->upperRight->getValueAt(layerFrame); + auto lowerRight = cornerPinEffect->lowerRight->getValueAt(layerFrame); + auto upperLeft = cornerPinEffect->upperLeft->getValueAt(layerFrame); + auto ll2ur_k = (upperRight.y - lowerLeft.y) / (upperRight.x - lowerLeft.x); + auto ul2lr_k = (lowerRight.y - upperLeft.y) / (lowerRight.x - upperLeft.x); + auto ll2ur_b = lowerLeft.y - ll2ur_k * lowerLeft.x; + auto ul2lr_b = upperLeft.y - ul2lr_k * upperLeft.x; + Point intersection = {0, 0}; + intersection.x = (ul2lr_b - ll2ur_b) / (ll2ur_k - ul2lr_k); + intersection.y = ll2ur_k * intersection.x + ll2ur_b; + // 计算对角线交点与4个顶点的距离 + auto lowerLeftDistance = calculateDistance(intersection, lowerLeft); + auto lowerRightDistance = calculateDistance(intersection, lowerRight); + auto upperRightDistance = calculateDistance(intersection, upperRight); + auto upperLeftDistance = calculateDistance(intersection, upperLeft); + // 计算4个顶点的uvq: uvq0 = float3(u0, v0, 1) * (d0 + d2) / d2 + if (PointIsBetween(intersection, lowerLeft, upperRight) && + PointIsBetween(intersection, upperLeft, lowerRight) && upperRightDistance != 0 && + upperLeftDistance != 0 && lowerRightDistance != 0 && lowerLeftDistance != 0) { + vertexQs[0] = (lowerLeftDistance + upperRightDistance) / upperRightDistance; // LowerLeft + vertexQs[1] = (lowerRightDistance + upperLeftDistance) / upperLeftDistance; // LowerRight + vertexQs[2] = (upperLeftDistance + lowerRightDistance) / lowerRightDistance; // UpperLeft + vertexQs[3] = (upperRightDistance + lowerLeftDistance) / lowerLeftDistance; // UpperRight + } else { + vertexQs[0] = 1.0f; + vertexQs[1] = 1.0f; + vertexQs[2] = 1.0f; + vertexQs[3] = 1.0f; + } } std::vector CornerPinFilter::computeVertices(const Rect& contentBounds, const Rect&, - const Point&) { - std::vector vertices = {}; - auto* cornerPinEffect = reinterpret_cast(effect); - Point contentPoint[4] = {cornerPinEffect->lowerLeft->getValueAt(layerFrame), - cornerPinEffect->lowerRight->getValueAt(layerFrame), - cornerPinEffect->upperLeft->getValueAt(layerFrame), - cornerPinEffect->upperRight->getValueAt(layerFrame)}; - Point texturePoints[4] = {{0.0f, contentBounds.height()}, - {contentBounds.width(), contentBounds.height()}, - {0.0f, 0.0f}, - {contentBounds.width(), 0.0f}}; + const Point&) { + std::vector vertices = {}; + auto* cornerPinEffect = reinterpret_cast(effect); + Point contentPoint[4] = {cornerPinEffect->lowerLeft->getValueAt(layerFrame), + cornerPinEffect->lowerRight->getValueAt(layerFrame), + cornerPinEffect->upperLeft->getValueAt(layerFrame), + cornerPinEffect->upperRight->getValueAt(layerFrame) + }; + Point texturePoints[4] = {{0.0f, contentBounds.height()}, + {contentBounds.width(), contentBounds.height()}, + {0.0f, 0.0f}, + {contentBounds.width(), 0.0f} + }; - for (int ii = 0; ii < 4; ii++) { - vertices.push_back(contentPoint[ii]); - vertices.push_back(texturePoints[ii]); - } - return vertices; + for (int ii = 0; ii < 4; ii++) { + vertices.push_back(contentPoint[ii]); + vertices.push_back(texturePoints[ii]); + } + return vertices; } void CornerPinFilter::bindVertices(const GLInterface* gl, const FilterSource* source, const FilterTarget* target, const std::vector& points) { - std::vector vertices = {}; - calculateVertexQs(); - for (size_t i = 0, j = 0; i < points.size() && j < 4; j++) { - auto vertexPoint = ToGLVertexPoint(target, source, contentBounds, points[i++]); - vertices.push_back(vertexPoint.x); - vertices.push_back(vertexPoint.y); - auto texturePoint = ToGLTexturePoint(source, points[i++]); - vertices.push_back(texturePoint.x * vertexQs[j]); - vertices.push_back(texturePoint.y * vertexQs[j]); - vertices.push_back(vertexQs[j]); - } + std::vector vertices = {}; + calculateVertexQs(); + for (size_t i = 0, j = 0; i < points.size() && j < 4; j++) { + auto vertexPoint = ToGLVertexPoint(target, source, contentBounds, points[i++]); + vertices.push_back(vertexPoint.x); + vertices.push_back(vertexPoint.y); + auto texturePoint = ToGLTexturePoint(source, points[i++]); + vertices.push_back(texturePoint.x * vertexQs[j]); + vertices.push_back(texturePoint.y * vertexQs[j]); + vertices.push_back(vertexQs[j]); + } - if (filterProgram->vertexArray > 0) { - gl->bindVertexArray(filterProgram->vertexArray); - } - gl->bindBuffer(GL::ARRAY_BUFFER, filterProgram->vertexBuffer); - gl->bufferData(GL::ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL::STREAM_DRAW); - gl->vertexAttribPointer(static_cast(positionHandle), 2, GL::FLOAT, GL::FALSE, - 5 * sizeof(float), static_cast(0)); - gl->enableVertexAttribArray(static_cast(positionHandle)); + if (filterProgram->vertexArray > 0) { + gl->bindVertexArray(filterProgram->vertexArray); + } + gl->bindBuffer(GL::ARRAY_BUFFER, filterProgram->vertexBuffer); + gl->bufferData(GL::ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL::STREAM_DRAW); + gl->vertexAttribPointer(static_cast(positionHandle), 2, GL::FLOAT, GL::FALSE, + 5 * sizeof(float), static_cast(0)); + gl->enableVertexAttribArray(static_cast(positionHandle)); - gl->vertexAttribPointer(textureCoordHandle, 3, GL::FLOAT, GL::FALSE, 5 * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - gl->enableVertexAttribArray(textureCoordHandle); - gl->bindBuffer(GL::ARRAY_BUFFER, 0); + gl->vertexAttribPointer(textureCoordHandle, 3, GL::FLOAT, GL::FALSE, 5 * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl->enableVertexAttribArray(textureCoordHandle); + gl->bindBuffer(GL::ARRAY_BUFFER, 0); } } // namespace pag diff --git a/src/rendering/filters/CornerPinFilter.h b/src/rendering/filters/CornerPinFilter.h index 93d6f30771..61e4f8aaad 100644 --- a/src/rendering/filters/CornerPinFilter.h +++ b/src/rendering/filters/CornerPinFilter.h @@ -22,29 +22,29 @@ namespace pag { class CornerPinFilter : public LayerFilter { - public: - explicit CornerPinFilter(Effect* effect); - ~CornerPinFilter() override = default; +public: + explicit CornerPinFilter(Effect* effect); + ~CornerPinFilter() override = default; - protected: - std::string onBuildVertexShader() override; +protected: + std::string onBuildVertexShader() override; - std::string onBuildFragmentShader() override; + std::string onBuildFragmentShader() override; - std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - void bindVertices(const GLInterface* gl, const FilterSource* source, const FilterTarget* target, - const std::vector& points) override; + void bindVertices(const GLInterface* gl, const FilterSource* source, const FilterTarget* target, + const std::vector& points) override; - bool needsMSAA() const override { - return true; - } + bool needsMSAA() const override { + return true; + } - private: - void calculateVertexQs(); +private: + void calculateVertexQs(); - Effect* effect = nullptr; - float vertexQs[4] = {1.0f}; + Effect* effect = nullptr; + float vertexQs[4] = {1.0f}; }; } // namespace pag diff --git a/src/rendering/filters/DisplacementMapFilter.cpp b/src/rendering/filters/DisplacementMapFilter.cpp index 10aad8cdb6..ad9da04f62 100644 --- a/src/rendering/filters/DisplacementMapFilter.cpp +++ b/src/rendering/filters/DisplacementMapFilter.cpp @@ -94,46 +94,46 @@ DisplacementMapFilter::DisplacementMapFilter(Effect* effect) : effect(effect) { } std::string DisplacementMapFilter::onBuildFragmentShader() { - return FRAGMENT_SHADER; + return FRAGMENT_SHADER; } void DisplacementMapFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - useForDisplacementHandle = gl->getUniformLocation(program, "uUseForDisplacement"); - maxDisplacementHandle = gl->getUniformLocation(program, "uMaxDisplacement"); - displacementMapBehaviorHandle = gl->getUniformLocation(program, "uDisplacementMapBehavior"); - edgeBehaviorHandle = gl->getUniformLocation(program, "uEdgeBehavior"); - expandOutputHandle = gl->getUniformLocation(program, "uExpandOutput"); - mapTextureHandle = gl->getUniformLocation(program, "mapTexture"); - mapTextureSizeHandle = gl->getUniformLocation(program, "mapTextureSize"); + useForDisplacementHandle = gl->getUniformLocation(program, "uUseForDisplacement"); + maxDisplacementHandle = gl->getUniformLocation(program, "uMaxDisplacement"); + displacementMapBehaviorHandle = gl->getUniformLocation(program, "uDisplacementMapBehavior"); + edgeBehaviorHandle = gl->getUniformLocation(program, "uEdgeBehavior"); + expandOutputHandle = gl->getUniformLocation(program, "uExpandOutput"); + mapTextureHandle = gl->getUniformLocation(program, "mapTexture"); + mapTextureSizeHandle = gl->getUniformLocation(program, "mapTextureSize"); } void DisplacementMapFilter::updateMapTexture(RenderCache* cache, const Graphic* mapGraphic, - const Rect& bounds) { - if (mapSurface == nullptr || mapBounds.width() != bounds.width() || - mapBounds.height() != bounds.height()) { - mapSurface = Surface::Make(cache->getContext(), static_cast(bounds.width()), - static_cast(bounds.height())); - mapBounds = bounds; - } - mapGraphic->draw(mapSurface->getCanvas(), cache); + const Rect& bounds) { + if (mapSurface == nullptr || mapBounds.width() != bounds.width() || + mapBounds.height() != bounds.height()) { + mapSurface = Surface::Make(cache->getContext(), static_cast(bounds.width()), + static_cast(bounds.height())); + mapBounds = bounds; + } + mapGraphic->draw(mapSurface->getCanvas(), cache); } void DisplacementMapFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point&) { - auto* pagEffect = reinterpret_cast(effect); - auto mapTexture = GLTexture::Unwrap(mapSurface->getTexture().get()); - ActiveTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, mapTexture.id); - gl->uniform2f(useForDisplacementHandle, - pagEffect->useForHorizontalDisplacement->getValueAt(layerFrame), - pagEffect->useForVerticalDisplacement->getValueAt(layerFrame)); - gl->uniform2f(maxDisplacementHandle, pagEffect->maxHorizontalDisplacement->getValueAt(layerFrame), - pagEffect->maxVerticalDisplacement->getValueAt(layerFrame)); - gl->uniform1i(displacementMapBehaviorHandle, - pagEffect->displacementMapBehavior->getValueAt(layerFrame)); - gl->uniform1i(edgeBehaviorHandle, pagEffect->edgeBehavior->getValueAt(layerFrame)); - gl->uniform1i(expandOutputHandle, pagEffect->expandOutput->getValueAt(layerFrame)); - gl->uniform1i(mapTextureHandle, 1); - gl->uniform2f(mapTextureSizeHandle, mapBounds.width() / contentBounds.width(), - mapBounds.height() / contentBounds.height()); + const Point&) { + auto* pagEffect = reinterpret_cast(effect); + auto mapTexture = GLTexture::Unwrap(mapSurface->getTexture().get()); + ActiveTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, mapTexture.id); + gl->uniform2f(useForDisplacementHandle, + pagEffect->useForHorizontalDisplacement->getValueAt(layerFrame), + pagEffect->useForVerticalDisplacement->getValueAt(layerFrame)); + gl->uniform2f(maxDisplacementHandle, pagEffect->maxHorizontalDisplacement->getValueAt(layerFrame), + pagEffect->maxVerticalDisplacement->getValueAt(layerFrame)); + gl->uniform1i(displacementMapBehaviorHandle, + pagEffect->displacementMapBehavior->getValueAt(layerFrame)); + gl->uniform1i(edgeBehaviorHandle, pagEffect->edgeBehavior->getValueAt(layerFrame)); + gl->uniform1i(expandOutputHandle, pagEffect->expandOutput->getValueAt(layerFrame)); + gl->uniform1i(mapTextureHandle, 1); + gl->uniform2f(mapTextureSizeHandle, mapBounds.width() / contentBounds.width(), + mapBounds.height() / contentBounds.height()); } } // namespace pag diff --git a/src/rendering/filters/DisplacementMapFilter.h b/src/rendering/filters/DisplacementMapFilter.h index ae263888ec..ae175b56e2 100644 --- a/src/rendering/filters/DisplacementMapFilter.h +++ b/src/rendering/filters/DisplacementMapFilter.h @@ -24,31 +24,31 @@ namespace pag { class RenderCache; class DisplacementMapFilter : public LayerFilter { - public: - explicit DisplacementMapFilter(Effect* effect); - ~DisplacementMapFilter() override = default; +public: + explicit DisplacementMapFilter(Effect* effect); + ~DisplacementMapFilter() override = default; - void updateMapTexture(RenderCache* cache, const Graphic* mapGraphic, const Rect& bounds); + void updateMapTexture(RenderCache* cache, const Graphic* mapGraphic, const Rect& bounds); - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; - Rect mapBounds = {}; - std::shared_ptr mapSurface = nullptr; +private: + Effect* effect = nullptr; + Rect mapBounds = {}; + std::shared_ptr mapSurface = nullptr; - int useForDisplacementHandle = 0; - int maxDisplacementHandle = 0; - int displacementMapBehaviorHandle = 0; - int edgeBehaviorHandle = 0; - int expandOutputHandle = 0; - int mapTextureHandle = 0; - int mapTextureSizeHandle = 0; + int useForDisplacementHandle = 0; + int maxDisplacementHandle = 0; + int displacementMapBehaviorHandle = 0; + int edgeBehaviorHandle = 0; + int expandOutputHandle = 0; + int mapTextureHandle = 0; + int mapTextureSizeHandle = 0; }; } // namespace pag diff --git a/src/rendering/filters/Filter.h b/src/rendering/filters/Filter.h index e64384febd..f95d4ef9f8 100644 --- a/src/rendering/filters/Filter.h +++ b/src/rendering/filters/Filter.h @@ -24,75 +24,75 @@ namespace pag { struct FilterSource { - /** - * the id of source texture. - */ - unsigned textureID = 0; + /** + * the id of source texture. + */ + unsigned textureID = 0; - /** - * The width of source texture in pixels after textureMatrix and scale being applied. - */ - int width = 0; + /** + * The width of source texture in pixels after textureMatrix and scale being applied. + */ + int width = 0; - /** - * The height of source texture in pixels after textureMatrix and scale being applied. - */ - int height = 0; + /** + * The height of source texture in pixels after textureMatrix and scale being applied. + */ + int height = 0; - /** - * Represent the scale factor of texture to the corresponding layer content. Filters need the - * scale factors to interpret scalar parameters representing pixel distances in the image.For - * example, a blur of 4 pixels should be interpreted as a blur of 2 pixels if the scale factor is - * 1/2 in each direction. - */ - Point scale = {}; + /** + * Represent the scale factor of texture to the corresponding layer content. Filters need the + * scale factors to interpret scalar parameters representing pixel distances in the image.For + * example, a blur of 4 pixels should be interpreted as a blur of 2 pixels if the scale factor is + * 1/2 in each direction. + */ + Point scale = {}; - /** - * The 3x3 texture coordinate transform matrix. This transform matrix maps 2D texture coordinates - * of the form (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture coordinate - * that should be used to sample that location from the texture. Sampling the texture outside of - * the range of this transform is undefined. The matrix is stored in column-major order so that it - * may be passed directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv functions. - */ - std::array textureMatrix = {}; + /** + * The 3x3 texture coordinate transform matrix. This transform matrix maps 2D texture coordinates + * of the form (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture coordinate + * that should be used to sample that location from the texture. Sampling the texture outside of + * the range of this transform is undefined. The matrix is stored in column-major order so that it + * may be passed directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv functions. + */ + std::array textureMatrix = {}; }; struct FilterTarget { - /** - * the id of target frame buffer. - */ - unsigned frameBufferID = 0; + /** + * the id of target frame buffer. + */ + unsigned frameBufferID = 0; - /** - * The width of target frame buffer in pixels. - */ - int width = 0; + /** + * The width of target frame buffer in pixels. + */ + int width = 0; - /** - * The height of target frame buffer in pixels. - */ - int height = 0; + /** + * The height of target frame buffer in pixels. + */ + int height = 0; - /** - * The 3x3 vertex coordinate transform matrix. The matrix is stored in column-major order so that - * it may be passed directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv functions. - */ - std::array vertexMatrix = {}; + /** + * The 3x3 vertex coordinate transform matrix. The matrix is stored in column-major order so that + * it may be passed directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv functions. + */ + std::array vertexMatrix = {}; }; class Filter { - public: - virtual ~Filter() = default; +public: + virtual ~Filter() = default; - virtual bool initialize(Context* context) = 0; + virtual bool initialize(Context* context) = 0; - /** - * Apply this filter to a filter source and draw it to a filter target. - */ - virtual void draw(Context* context, const FilterSource* source, const FilterTarget* target) = 0; + /** + * Apply this filter to a filter source and draw it to a filter target. + */ + virtual void draw(Context* context, const FilterSource* source, const FilterTarget* target) = 0; - virtual bool needsMSAA() const { - return false; - } + virtual bool needsMSAA() const { + return false; + } }; } // namespace pag diff --git a/src/rendering/filters/FilterModifier.cpp b/src/rendering/filters/FilterModifier.cpp index 815e7efc7d..4e1694de2c 100644 --- a/src/rendering/filters/FilterModifier.cpp +++ b/src/rendering/filters/FilterModifier.cpp @@ -23,32 +23,32 @@ namespace pag { std::shared_ptr FilterModifier::Make(PAGLayer* pagLayer) { - if (pagLayer == nullptr || pagLayer->contentFrame < 0 || - pagLayer->contentFrame >= pagLayer->layer->duration) { - return nullptr; - } - auto modifier = Make(pagLayer->layer, pagLayer->layer->startTime + pagLayer->contentFrame); - return modifier; + if (pagLayer == nullptr || pagLayer->contentFrame < 0 || + pagLayer->contentFrame >= pagLayer->layer->duration) { + return nullptr; + } + auto modifier = Make(pagLayer->layer, pagLayer->layer->startTime + pagLayer->contentFrame); + return modifier; } std::shared_ptr FilterModifier::Make(Layer* layer, Frame layerFrame) { - if (layer == nullptr || layerFrame < layer->startTime || - layerFrame >= layer->startTime + layer->duration || - (!layer->motionBlur && layer->effects.empty() && layer->layerStyles.empty())) { - return nullptr; - } - auto modifier = std::shared_ptr(new FilterModifier()); - modifier->layer = layer; - modifier->layerFrame = layerFrame; - return modifier; + if (layer == nullptr || layerFrame < layer->startTime || + layerFrame >= layer->startTime + layer->duration || + (!layer->motionBlur && layer->effects.empty() && layer->layerStyles.empty())) { + return nullptr; + } + auto modifier = std::shared_ptr(new FilterModifier()); + modifier->layer = layer; + modifier->layerFrame = layerFrame; + return modifier; } void FilterModifier::applyToBounds(Rect* bounds) const { - FilterRenderer::MeasureFilterBounds(bounds, this); + FilterRenderer::MeasureFilterBounds(bounds, this); } void FilterModifier::applyToGraphic(Canvas* canvas, RenderCache* cache, std::shared_ptr graphic) const { - FilterRenderer::DrawWithFilter(static_cast(canvas), cache, this, graphic); + FilterRenderer::DrawWithFilter(static_cast(canvas), cache, this, graphic); } } // namespace pag diff --git a/src/rendering/filters/FilterModifier.h b/src/rendering/filters/FilterModifier.h index 24494ee120..7729c5d1a0 100644 --- a/src/rendering/filters/FilterModifier.h +++ b/src/rendering/filters/FilterModifier.h @@ -25,47 +25,47 @@ namespace pag { class FilterModifier : public Modifier { - public: - /** - * Returns nullptr if trackMatteLayer is nullptr. - */ - static std::shared_ptr Make(PAGLayer* pagLayer); +public: + /** + * Returns nullptr if trackMatteLayer is nullptr. + */ + static std::shared_ptr Make(PAGLayer* pagLayer); - /** - * Returns nullptr if trackMatteLayer is nullptr. - */ - static std::shared_ptr Make(Layer* layer, Frame layerFrame); + /** + * Returns nullptr if trackMatteLayer is nullptr. + */ + static std::shared_ptr Make(Layer* layer, Frame layerFrame); - ID type() const override { - static const auto TypeID = UniqueID::Next(); - return TypeID; - } + ID type() const override { + static const auto TypeID = UniqueID::Next(); + return TypeID; + } - bool isEmpty() const override { - return false; - } + bool isEmpty() const override { + return false; + } - bool hitTest(RenderCache*, float, float) const override { - return true; - } + bool hitTest(RenderCache*, float, float) const override { + return true; + } - void prepare(RenderCache*) const override { - } + void prepare(RenderCache*) const override { + } - void applyToBounds(Rect* bounds) const override; + void applyToBounds(Rect* bounds) const override; - bool applyToPath(Path*) const override { - return false; - } + bool applyToPath(Path*) const override { + return false; + } - void applyToGraphic(Canvas* canvas, RenderCache* cache, - std::shared_ptr graphic) const override; + void applyToGraphic(Canvas* canvas, RenderCache* cache, + std::shared_ptr graphic) const override; - std::shared_ptr mergeWith(const Modifier*) const override { - return nullptr; - } + std::shared_ptr mergeWith(const Modifier*) const override { + return nullptr; + } - Layer* layer = nullptr; - Frame layerFrame = 0; + Layer* layer = nullptr; + Frame layerFrame = 0; }; } // namespace pag diff --git a/src/rendering/filters/LayerFilter.h b/src/rendering/filters/LayerFilter.h index d21e1e70e3..b5b1637d58 100644 --- a/src/rendering/filters/LayerFilter.h +++ b/src/rendering/filters/LayerFilter.h @@ -25,106 +25,106 @@ namespace pag { std::vector ComputeVerticesForMotionBlurAndBulge(const Rect& inputBounds, - const Rect& outputBounds); + const Rect& outputBounds); class FilterProgram : public Resource { - public: - static std::shared_ptr Make(Context* context, const std::string& vertex, - const std::string& fragment); +public: + static std::shared_ptr Make(Context* context, const std::string& vertex, + const std::string& fragment); - unsigned program = 0; - unsigned int vertexArray = 0; - unsigned int vertexBuffer = 0; + unsigned program = 0; + unsigned int vertexArray = 0; + unsigned int vertexBuffer = 0; - protected: - void onRelease(Context* context) override; +protected: + void onRelease(Context* context) override; - private: - FilterProgram() = default; +private: + FilterProgram() = default; }; class LayerFilter : public Filter { - public: - static std::unique_ptr Make(LayerStyle* layerStyle); - - static std::unique_ptr Make(Effect* effect); - - bool initialize(Context* context) override; - - virtual bool needsMSAA() const override; - - /** - * filter的绘制接口 - * 单次render pass的滤镜无需重载该接口,只有滤镜需经过多次render pass时,才重载该函数的实现 - * 具体样例参见: DropShadow、Glow、GaussBlur这几个滤镜。 - * @param source : 滤镜的输入source, - * 该参数里含有纹理的ID、像素级的宽高、纹理点的matrix、以及纹理相对于layer bounds的scale信息 - * @param target : 滤镜的输出target,该参数里含有frame buffer的ID、像素级的宽高、顶点的matrix信息 - */ - void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; - - /** - * filter的刷新接口。 - * 单次render pass的滤镜无需重载该接口,只有滤镜需经过多次render pass时,才重载该函数的实现 - * 具体样例参见: DropShadow、Glow、GaussBlur这几个滤镜。 - * @param layerFrame : 当前绘制的layerFrame, 主要用来从effect或者style中获取滤镜所需的参数 - * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域 - * @param transformedBounds : 滤镜输出的基于layer bounds尺寸的矩形区域 - * @param filterScale : - * 滤镜效果的scale,比如LayerStyle本应该在图层matrix之后应用的,但是我们为了简化渲染改到了matrix之前, - * 因此需要反向排除图层matrix的缩放值 - * 该filterScale等于反向matrix的scale,不包含source.scale, - * source.scale会整体应用到FilterTarget上屏的matrix里。 - */ - virtual void update(Frame layerFrame, const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale); - - protected: - Frame layerFrame = 0; - std::shared_ptr filterProgram = nullptr; - - virtual std::string onBuildVertexShader(); - - virtual std::string onBuildFragmentShader(); - - virtual void onPrepareProgram(const GLInterface* gl, unsigned program); - - /** - * filter的给shader上传数据接口 - * 单次render pass的滤镜需重载该接口。具体样例参见:Bulge、MotionBlur、MotionTile - * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域,某些滤镜需要用到content - * bounds来计算shader中的参数,比如:bulge、MotionTile - * @param filterScale : 滤镜效果的scale - */ - virtual void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale); - - /** - * filter的收集顶点数据的接口 - * 单次render pass的滤镜需重载该接口。具体样例参见:Bulge、MotionBlur、MotionTile - * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域 - * @param transformedBounds : 滤镜输出的基于layer bounds尺寸的矩形区域 - * @param filterScale : 滤镜效果的scale - * @return : 返回顶点与纹理的point数组,顶点 + 纹理 + 顶点 + - * 纹理的组合方式,所有的Point都是基于layer bounds尺寸的点 - */ - virtual std::vector computeVertices(const Rect& contentBounds, - const Rect& transformedBounds, - const Point& filterScale); - - virtual void bindVertices(const GLInterface* gl, const FilterSource* source, - const FilterTarget* target, const std::vector& points); - - private: - Rect contentBounds = {}; - Rect transformedBounds = {}; - Point filterScale = {}; - - int vertexMatrixHandle = -1; - int textureMatrixHandle = -1; - int positionHandle = -1; - int textureCoordHandle = -1; - - friend class CornerPinFilter; +public: + static std::unique_ptr Make(LayerStyle* layerStyle); + + static std::unique_ptr Make(Effect* effect); + + bool initialize(Context* context) override; + + virtual bool needsMSAA() const override; + + /** + * filter的绘制接口 + * 单次render pass的滤镜无需重载该接口,只有滤镜需经过多次render pass时,才重载该函数的实现 + * 具体样例参见: DropShadow、Glow、GaussBlur这几个滤镜。 + * @param source : 滤镜的输入source, + * 该参数里含有纹理的ID、像素级的宽高、纹理点的matrix、以及纹理相对于layer bounds的scale信息 + * @param target : 滤镜的输出target,该参数里含有frame buffer的ID、像素级的宽高、顶点的matrix信息 + */ + void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; + + /** + * filter的刷新接口。 + * 单次render pass的滤镜无需重载该接口,只有滤镜需经过多次render pass时,才重载该函数的实现 + * 具体样例参见: DropShadow、Glow、GaussBlur这几个滤镜。 + * @param layerFrame : 当前绘制的layerFrame, 主要用来从effect或者style中获取滤镜所需的参数 + * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域 + * @param transformedBounds : 滤镜输出的基于layer bounds尺寸的矩形区域 + * @param filterScale : + * 滤镜效果的scale,比如LayerStyle本应该在图层matrix之后应用的,但是我们为了简化渲染改到了matrix之前, + * 因此需要反向排除图层matrix的缩放值 + * 该filterScale等于反向matrix的scale,不包含source.scale, + * source.scale会整体应用到FilterTarget上屏的matrix里。 + */ + virtual void update(Frame layerFrame, const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale); + +protected: + Frame layerFrame = 0; + std::shared_ptr filterProgram = nullptr; + + virtual std::string onBuildVertexShader(); + + virtual std::string onBuildFragmentShader(); + + virtual void onPrepareProgram(const GLInterface* gl, unsigned program); + + /** + * filter的给shader上传数据接口 + * 单次render pass的滤镜需重载该接口。具体样例参见:Bulge、MotionBlur、MotionTile + * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域,某些滤镜需要用到content + * bounds来计算shader中的参数,比如:bulge、MotionTile + * @param filterScale : 滤镜效果的scale + */ + virtual void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale); + + /** + * filter的收集顶点数据的接口 + * 单次render pass的滤镜需重载该接口。具体样例参见:Bulge、MotionBlur、MotionTile + * @param contentBounds : 滤镜输入的基于layer bounds尺寸的矩形区域 + * @param transformedBounds : 滤镜输出的基于layer bounds尺寸的矩形区域 + * @param filterScale : 滤镜效果的scale + * @return : 返回顶点与纹理的point数组,顶点 + 纹理 + 顶点 + + * 纹理的组合方式,所有的Point都是基于layer bounds尺寸的点 + */ + virtual std::vector computeVertices(const Rect& contentBounds, + const Rect& transformedBounds, + const Point& filterScale); + + virtual void bindVertices(const GLInterface* gl, const FilterSource* source, + const FilterTarget* target, const std::vector& points); + +private: + Rect contentBounds = {}; + Rect transformedBounds = {}; + Point filterScale = {}; + + int vertexMatrixHandle = -1; + int textureMatrixHandle = -1; + int positionHandle = -1; + int textureCoordHandle = -1; + + friend class CornerPinFilter; }; } // namespace pag diff --git a/src/rendering/filters/LayerStylesFilter.cpp b/src/rendering/filters/LayerStylesFilter.cpp index 65b481f31b..fda63cee06 100644 --- a/src/rendering/filters/LayerStylesFilter.cpp +++ b/src/rendering/filters/LayerStylesFilter.cpp @@ -22,57 +22,57 @@ namespace pag { void LayerStylesFilter::TransformBounds(Rect* bounds, const FilterList* filterList) { - for (auto& layerStyle : filterList->layerStyles) { - auto rect = *bounds; - layerStyle->transformBounds(&rect, filterList->layerStyleScale, filterList->layerFrame); - rect.roundOut(); - bounds->join(rect); - } + for (auto& layerStyle : filterList->layerStyles) { + auto rect = *bounds; + layerStyle->transformBounds(&rect, filterList->layerStyleScale, filterList->layerFrame); + rect.roundOut(); + bounds->join(rect); + } } LayerStylesFilter::LayerStylesFilter(RenderCache* renderCache) : renderCache(renderCache) { - drawFilter = new LayerFilter(); + drawFilter = new LayerFilter(); } LayerStylesFilter::~LayerStylesFilter() { - delete drawFilter; + delete drawFilter; } bool LayerStylesFilter::initialize(Context* context) { - return drawFilter->initialize(context); + return drawFilter->initialize(context); } void LayerStylesFilter::update(const FilterList* list, const Rect& inputBounds, const Rect& outputBounds, const Point& extraScale) { - filterList = list; - contentBounds = inputBounds; - transformedBounds = outputBounds; - filterScale = extraScale; + filterList = list; + contentBounds = inputBounds; + transformedBounds = outputBounds; + filterScale = extraScale; } void LayerStylesFilter::draw(Context* context, const FilterSource* source, const FilterTarget* target) { - for (auto& layerStyle : filterList->layerStyles) { - if (layerStyle->drawPosition() == LayerStylePosition::Blow) { - auto filter = renderCache->getFilterCache(layerStyle); - if (filter) { - filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale); - filter->draw(context, source, target); - } + for (auto& layerStyle : filterList->layerStyles) { + if (layerStyle->drawPosition() == LayerStylePosition::Blow) { + auto filter = renderCache->getFilterCache(layerStyle); + if (filter) { + filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale); + filter->draw(context, source, target); + } + } } - } - drawFilter->update(filterList->layerFrame, contentBounds, contentBounds, filterScale); - drawFilter->draw(context, source, target); + drawFilter->update(filterList->layerFrame, contentBounds, contentBounds, filterScale); + drawFilter->draw(context, source, target); - for (auto& layerStyle : filterList->layerStyles) { - if (layerStyle->drawPosition() == LayerStylePosition::Above) { - auto filter = renderCache->getFilterCache(layerStyle); - if (filter) { - filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale); - filter->draw(context, source, target); - } + for (auto& layerStyle : filterList->layerStyles) { + if (layerStyle->drawPosition() == LayerStylePosition::Above) { + auto filter = renderCache->getFilterCache(layerStyle); + if (filter) { + filter->update(filterList->layerFrame, contentBounds, transformedBounds, filterScale); + filter->draw(context, source, target); + } + } } - } } } // namespace pag diff --git a/src/rendering/filters/LayerStylesFilter.h b/src/rendering/filters/LayerStylesFilter.h index ad022f30a1..1ef73f3ac2 100644 --- a/src/rendering/filters/LayerStylesFilter.h +++ b/src/rendering/filters/LayerStylesFilter.h @@ -28,26 +28,26 @@ class RenderCache; struct FilterList; class LayerStylesFilter : public Filter { - public: - static void TransformBounds(Rect* bounds, const FilterList* filterList); +public: + static void TransformBounds(Rect* bounds, const FilterList* filterList); - explicit LayerStylesFilter(RenderCache* renderCache); + explicit LayerStylesFilter(RenderCache* renderCache); - ~LayerStylesFilter() override; + ~LayerStylesFilter() override; - bool initialize(Context* context) override; + bool initialize(Context* context) override; - void update(const FilterList* filterList, const Rect& contentBounds, - const Rect& transformedBounds, const Point& filterScale); + void update(const FilterList* filterList, const Rect& contentBounds, + const Rect& transformedBounds, const Point& filterScale); - void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; + void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; - private: - const FilterList* filterList = nullptr; - RenderCache* renderCache = nullptr; - LayerFilter* drawFilter = nullptr; - Rect contentBounds = {}; - Rect transformedBounds = {}; - Point filterScale = {}; +private: + const FilterList* filterList = nullptr; + RenderCache* renderCache = nullptr; + LayerFilter* drawFilter = nullptr; + Rect contentBounds = {}; + Rect transformedBounds = {}; + Point filterScale = {}; }; } // namespace pag diff --git a/src/rendering/filters/LevelsIndividualFilter.cpp b/src/rendering/filters/LevelsIndividualFilter.cpp index 53d3b0d75b..cb8fa5d085 100644 --- a/src/rendering/filters/LevelsIndividualFilter.cpp +++ b/src/rendering/filters/LevelsIndividualFilter.cpp @@ -84,69 +84,69 @@ LevelsIndividualFilter::LevelsIndividualFilter(pag::Effect* effect) : effect(eff } std::string LevelsIndividualFilter::onBuildFragmentShader() { - return FRAGMENT_SHADER; + return FRAGMENT_SHADER; } void LevelsIndividualFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - inputBlackHandle = gl->getUniformLocation(program, "inputBlack"); - inputWhiteHandle = gl->getUniformLocation(program, "inputWhite"); - gammaHandle = gl->getUniformLocation(program, "gamma"); - outputBlackHandle = gl->getUniformLocation(program, "outputBlack"); - outputWhiteHandle = gl->getUniformLocation(program, "outputWhite"); - - redInputBlackHandle = gl->getUniformLocation(program, "redInputBlack"); - redInputWhiteHandle = gl->getUniformLocation(program, "redInputWhite"); - redGammaHandle = gl->getUniformLocation(program, "redGamma"); - redOutputBlackHandle = gl->getUniformLocation(program, "redOutputBlack"); - redOutputWhiteHandle = gl->getUniformLocation(program, "redOutputWhite"); - - greenInputBlackHandle = gl->getUniformLocation(program, "greenInputBlack"); - greenInputWhiteHandle = gl->getUniformLocation(program, "greenInputWhite"); - greenGammaHandle = gl->getUniformLocation(program, "greenGamma"); - greenOutputBlackHandle = gl->getUniformLocation(program, "greenOutputBlack"); - greenOutputWhiteHandle = gl->getUniformLocation(program, "greenOutputWhite"); - - blueInputBlackHandle = gl->getUniformLocation(program, "blueInputBlack"); - blueInputWhiteHandle = gl->getUniformLocation(program, "blueInputWhite"); - blueGammaHandle = gl->getUniformLocation(program, "blueGamma"); - blueOutputBlackHandle = gl->getUniformLocation(program, "blueOutputBlack"); - blueOutputWhiteHandle = gl->getUniformLocation(program, "blueOutputWhite"); + inputBlackHandle = gl->getUniformLocation(program, "inputBlack"); + inputWhiteHandle = gl->getUniformLocation(program, "inputWhite"); + gammaHandle = gl->getUniformLocation(program, "gamma"); + outputBlackHandle = gl->getUniformLocation(program, "outputBlack"); + outputWhiteHandle = gl->getUniformLocation(program, "outputWhite"); + + redInputBlackHandle = gl->getUniformLocation(program, "redInputBlack"); + redInputWhiteHandle = gl->getUniformLocation(program, "redInputWhite"); + redGammaHandle = gl->getUniformLocation(program, "redGamma"); + redOutputBlackHandle = gl->getUniformLocation(program, "redOutputBlack"); + redOutputWhiteHandle = gl->getUniformLocation(program, "redOutputWhite"); + + greenInputBlackHandle = gl->getUniformLocation(program, "greenInputBlack"); + greenInputWhiteHandle = gl->getUniformLocation(program, "greenInputWhite"); + greenGammaHandle = gl->getUniformLocation(program, "greenGamma"); + greenOutputBlackHandle = gl->getUniformLocation(program, "greenOutputBlack"); + greenOutputWhiteHandle = gl->getUniformLocation(program, "greenOutputWhite"); + + blueInputBlackHandle = gl->getUniformLocation(program, "blueInputBlack"); + blueInputWhiteHandle = gl->getUniformLocation(program, "blueInputWhite"); + blueGammaHandle = gl->getUniformLocation(program, "blueGamma"); + blueOutputBlackHandle = gl->getUniformLocation(program, "blueOutputBlack"); + blueOutputWhiteHandle = gl->getUniformLocation(program, "blueOutputWhite"); } void LevelsIndividualFilter::onUpdateParams(const GLInterface* gl, const Rect&, const Point&) { - auto* levelsIndividualFilter = reinterpret_cast(effect); - gl->uniform1f(inputBlackHandle, levelsIndividualFilter->inputBlack->getValueAt(layerFrame)); - gl->uniform1f(inputWhiteHandle, levelsIndividualFilter->inputWhite->getValueAt(layerFrame)); - gl->uniform1f(gammaHandle, levelsIndividualFilter->gamma->getValueAt(layerFrame)); - gl->uniform1f(outputBlackHandle, levelsIndividualFilter->outputBlack->getValueAt(layerFrame)); - gl->uniform1f(outputWhiteHandle, levelsIndividualFilter->outputWhite->getValueAt(layerFrame)); - - gl->uniform1f(redInputBlackHandle, levelsIndividualFilter->redInputBlack->getValueAt(layerFrame)); - gl->uniform1f(redInputWhiteHandle, levelsIndividualFilter->redInputWhite->getValueAt(layerFrame)); - gl->uniform1f(redGammaHandle, levelsIndividualFilter->redGamma->getValueAt(layerFrame)); - gl->uniform1f(redOutputBlackHandle, - levelsIndividualFilter->redOutputBlack->getValueAt(layerFrame)); - gl->uniform1f(redOutputWhiteHandle, - levelsIndividualFilter->redOutputWhite->getValueAt(layerFrame)); - - gl->uniform1f(greenInputBlackHandle, - levelsIndividualFilter->greenInputBlack->getValueAt(layerFrame)); - gl->uniform1f(greenInputWhiteHandle, - levelsIndividualFilter->greenInputWhite->getValueAt(layerFrame)); - gl->uniform1f(greenGammaHandle, levelsIndividualFilter->greenGamma->getValueAt(layerFrame)); - gl->uniform1f(greenOutputBlackHandle, - levelsIndividualFilter->greenOutputBlack->getValueAt(layerFrame)); - gl->uniform1f(greenOutputWhiteHandle, - levelsIndividualFilter->greenOutputWhite->getValueAt(layerFrame)); - - gl->uniform1f(blueInputBlackHandle, - levelsIndividualFilter->blueInputBlack->getValueAt(layerFrame)); - gl->uniform1f(blueInputWhiteHandle, - levelsIndividualFilter->blueInputWhite->getValueAt(layerFrame)); - gl->uniform1f(blueGammaHandle, levelsIndividualFilter->blueGamma->getValueAt(layerFrame)); - gl->uniform1f(blueOutputBlackHandle, - levelsIndividualFilter->blueOutputBlack->getValueAt(layerFrame)); - gl->uniform1f(blueOutputWhiteHandle, - levelsIndividualFilter->blueOutputWhite->getValueAt(layerFrame)); + auto* levelsIndividualFilter = reinterpret_cast(effect); + gl->uniform1f(inputBlackHandle, levelsIndividualFilter->inputBlack->getValueAt(layerFrame)); + gl->uniform1f(inputWhiteHandle, levelsIndividualFilter->inputWhite->getValueAt(layerFrame)); + gl->uniform1f(gammaHandle, levelsIndividualFilter->gamma->getValueAt(layerFrame)); + gl->uniform1f(outputBlackHandle, levelsIndividualFilter->outputBlack->getValueAt(layerFrame)); + gl->uniform1f(outputWhiteHandle, levelsIndividualFilter->outputWhite->getValueAt(layerFrame)); + + gl->uniform1f(redInputBlackHandle, levelsIndividualFilter->redInputBlack->getValueAt(layerFrame)); + gl->uniform1f(redInputWhiteHandle, levelsIndividualFilter->redInputWhite->getValueAt(layerFrame)); + gl->uniform1f(redGammaHandle, levelsIndividualFilter->redGamma->getValueAt(layerFrame)); + gl->uniform1f(redOutputBlackHandle, + levelsIndividualFilter->redOutputBlack->getValueAt(layerFrame)); + gl->uniform1f(redOutputWhiteHandle, + levelsIndividualFilter->redOutputWhite->getValueAt(layerFrame)); + + gl->uniform1f(greenInputBlackHandle, + levelsIndividualFilter->greenInputBlack->getValueAt(layerFrame)); + gl->uniform1f(greenInputWhiteHandle, + levelsIndividualFilter->greenInputWhite->getValueAt(layerFrame)); + gl->uniform1f(greenGammaHandle, levelsIndividualFilter->greenGamma->getValueAt(layerFrame)); + gl->uniform1f(greenOutputBlackHandle, + levelsIndividualFilter->greenOutputBlack->getValueAt(layerFrame)); + gl->uniform1f(greenOutputWhiteHandle, + levelsIndividualFilter->greenOutputWhite->getValueAt(layerFrame)); + + gl->uniform1f(blueInputBlackHandle, + levelsIndividualFilter->blueInputBlack->getValueAt(layerFrame)); + gl->uniform1f(blueInputWhiteHandle, + levelsIndividualFilter->blueInputWhite->getValueAt(layerFrame)); + gl->uniform1f(blueGammaHandle, levelsIndividualFilter->blueGamma->getValueAt(layerFrame)); + gl->uniform1f(blueOutputBlackHandle, + levelsIndividualFilter->blueOutputBlack->getValueAt(layerFrame)); + gl->uniform1f(blueOutputWhiteHandle, + levelsIndividualFilter->blueOutputWhite->getValueAt(layerFrame)); } } // namespace pag diff --git a/src/rendering/filters/LevelsIndividualFilter.h b/src/rendering/filters/LevelsIndividualFilter.h index 2d9a3b0985..785565b604 100644 --- a/src/rendering/filters/LevelsIndividualFilter.h +++ b/src/rendering/filters/LevelsIndividualFilter.h @@ -22,44 +22,44 @@ namespace pag { class LevelsIndividualFilter : public LayerFilter { - public: - explicit LevelsIndividualFilter(Effect* effect); - ~LevelsIndividualFilter() override = default; +public: + explicit LevelsIndividualFilter(Effect* effect); + ~LevelsIndividualFilter() override = default; - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - // Handle - int inputBlackHandle; - int inputWhiteHandle; - int gammaHandle; - int outputBlackHandle; - int outputWhiteHandle; + // Handle + int inputBlackHandle; + int inputWhiteHandle; + int gammaHandle; + int outputBlackHandle; + int outputWhiteHandle; - int redInputBlackHandle; - int redInputWhiteHandle; - int redGammaHandle; - int redOutputBlackHandle; - int redOutputWhiteHandle; + int redInputBlackHandle; + int redInputWhiteHandle; + int redGammaHandle; + int redOutputBlackHandle; + int redOutputWhiteHandle; - int blueInputBlackHandle; - int blueInputWhiteHandle; - int blueGammaHandle; - int blueOutputBlackHandle; - int blueOutputWhiteHandle; + int blueInputBlackHandle; + int blueInputWhiteHandle; + int blueGammaHandle; + int blueOutputBlackHandle; + int blueOutputWhiteHandle; - int greenInputBlackHandle; - int greenInputWhiteHandle; - int greenGammaHandle; - int greenOutputBlackHandle; - int greenOutputWhiteHandle; + int greenInputBlackHandle; + int greenInputWhiteHandle; + int greenGammaHandle; + int greenOutputBlackHandle; + int greenOutputWhiteHandle; }; } // namespace pag diff --git a/src/rendering/filters/MosaicFilter.cpp b/src/rendering/filters/MosaicFilter.cpp index 714a50c6ab..73bafe8a84 100644 --- a/src/rendering/filters/MosaicFilter.cpp +++ b/src/rendering/filters/MosaicFilter.cpp @@ -41,37 +41,37 @@ MosaicFilter::MosaicFilter(pag::Effect* effect) : effect(effect) { } std::string MosaicFilter::onBuildFragmentShader() { - return FRAGMENT_SHADER; + return FRAGMENT_SHADER; } void MosaicFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - horizontalBlocksHandle = gl->getUniformLocation(program, "mHorizontalBlocks"); - verticalBlocksHandle = gl->getUniformLocation(program, "mVerticalBlocks"); - sharpColorsHandle = gl->getUniformLocation(program, "mSharpColors"); + horizontalBlocksHandle = gl->getUniformLocation(program, "mHorizontalBlocks"); + verticalBlocksHandle = gl->getUniformLocation(program, "mVerticalBlocks"); + sharpColorsHandle = gl->getUniformLocation(program, "mSharpColors"); } void MosaicFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, const Point&) { - auto* mosaicEffect = reinterpret_cast(effect); - horizontalBlocks = 1.0f / mosaicEffect->horizontalBlocks->getValueAt(layerFrame); - verticalBlocks = 1.0f / mosaicEffect->verticalBlocks->getValueAt(layerFrame); - sharpColors = mosaicEffect->sharpColors->getValueAt(layerFrame); + auto* mosaicEffect = reinterpret_cast(effect); + horizontalBlocks = 1.0f / mosaicEffect->horizontalBlocks->getValueAt(layerFrame); + verticalBlocks = 1.0f / mosaicEffect->verticalBlocks->getValueAt(layerFrame); + sharpColors = mosaicEffect->sharpColors->getValueAt(layerFrame); - auto placeHolderWidth = static_cast(contentBounds.left + contentBounds.right); - auto placeHolderHeight = static_cast(contentBounds.top + contentBounds.bottom); - auto placeHolderRatio = 1.0f * placeHolderWidth / placeHolderHeight; + auto placeHolderWidth = static_cast(contentBounds.left + contentBounds.right); + auto placeHolderHeight = static_cast(contentBounds.top + contentBounds.bottom); + auto placeHolderRatio = 1.0f * placeHolderWidth / placeHolderHeight; - auto contentWidth = static_cast(contentBounds.width()); - auto contentHeight = static_cast(contentBounds.height()); - auto contentRatio = 1.0f * contentWidth / contentHeight; + auto contentWidth = static_cast(contentBounds.width()); + auto contentHeight = static_cast(contentBounds.height()); + auto contentRatio = 1.0f * contentWidth / contentHeight; - if (placeHolderRatio > contentRatio) { - horizontalBlocks *= 1.0f * placeHolderWidth / contentWidth; - } else { - verticalBlocks *= 1.0f * placeHolderHeight / contentHeight; - } + if (placeHolderRatio > contentRatio) { + horizontalBlocks *= 1.0f * placeHolderWidth / contentWidth; + } else { + verticalBlocks *= 1.0f * placeHolderHeight / contentHeight; + } - gl->uniform1f(horizontalBlocksHandle, horizontalBlocks); - gl->uniform1f(verticalBlocksHandle, verticalBlocks); - gl->uniform1f(sharpColorsHandle, sharpColors); + gl->uniform1f(horizontalBlocksHandle, horizontalBlocks); + gl->uniform1f(verticalBlocksHandle, verticalBlocks); + gl->uniform1f(sharpColorsHandle, sharpColors); } } // namespace pag diff --git a/src/rendering/filters/MosaicFilter.h b/src/rendering/filters/MosaicFilter.h index 820a5a7663..2620ed8c09 100644 --- a/src/rendering/filters/MosaicFilter.h +++ b/src/rendering/filters/MosaicFilter.h @@ -22,27 +22,27 @@ namespace pag { class MosaicFilter : public LayerFilter { - public: - explicit MosaicFilter(Effect* effect); - ~MosaicFilter() override = default; +public: + explicit MosaicFilter(Effect* effect); + ~MosaicFilter() override = default; - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; - float horizontalBlocks = 1; - float verticalBlocks = 1; - bool sharpColors = false; +private: + Effect* effect = nullptr; + float horizontalBlocks = 1; + float verticalBlocks = 1; + bool sharpColors = false; - // Handle - int horizontalBlocksHandle = -1; - int verticalBlocksHandle = -1; - int sharpColorsHandle = -1; + // Handle + int horizontalBlocksHandle = -1; + int verticalBlocksHandle = -1; + int sharpColorsHandle = -1; }; } // namespace pag diff --git a/src/rendering/filters/MotionBlurFilter.cpp b/src/rendering/filters/MotionBlurFilter.cpp index 273348c513..7fc7524ca6 100644 --- a/src/rendering/filters/MotionBlurFilter.cpp +++ b/src/rendering/filters/MotionBlurFilter.cpp @@ -83,67 +83,67 @@ static const char MOTIONBLUR_FRAGMENT_SHADER[] = R"( )"; void MotionBlurFilter::TransformBounds(Rect* bounds, const Point&, Layer* layer, Frame layerFrame) { - auto contentFrame = layerFrame - layer->startTime; - auto layerCache = LayerCache::Get(layer); - auto previousMatrix = layerCache->getTransform(contentFrame > 0 ? contentFrame - 1 : 0)->matrix; - auto currentMatrix = layerCache->getTransform(contentFrame)->matrix; - if (previousMatrix != currentMatrix) { - auto width = bounds->width() * MOTION_BLUR_SCALE_FACTOR; - auto height = bounds->height() * MOTION_BLUR_SCALE_FACTOR; - auto x = bounds->x() + (bounds->width() - width) * 0.5f; - auto y = bounds->y() + (bounds->height() - height) * 0.5f; - bounds->setXYWH(x, y, width, height); - } + auto contentFrame = layerFrame - layer->startTime; + auto layerCache = LayerCache::Get(layer); + auto previousMatrix = layerCache->getTransform(contentFrame > 0 ? contentFrame - 1 : 0)->matrix; + auto currentMatrix = layerCache->getTransform(contentFrame)->matrix; + if (previousMatrix != currentMatrix) { + auto width = bounds->width() * MOTION_BLUR_SCALE_FACTOR; + auto height = bounds->height() * MOTION_BLUR_SCALE_FACTOR; + auto x = bounds->x() + (bounds->width() - width) * 0.5f; + auto y = bounds->y() + (bounds->height() - height) * 0.5f; + bounds->setXYWH(x, y, width, height); + } } MotionBlurFilter::MotionBlurFilter() { } std::string MotionBlurFilter::onBuildVertexShader() { - return MOTIONBLUR_VERTEX_SHADER; + return MOTIONBLUR_VERTEX_SHADER; } std::string MotionBlurFilter::onBuildFragmentShader() { - return MOTIONBLUR_FRAGMENT_SHADER; + return MOTIONBLUR_FRAGMENT_SHADER; } void MotionBlurFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - prevTransformHandle = gl->getUniformLocation(program, "uPrevTransform"); - transformHandle = gl->getUniformLocation(program, "uTransform"); - velCenterHandle = gl->getUniformLocation(program, "uVelCenter"); - maxDistanceHandle = gl->getUniformLocation(program, "maxDistance"); + prevTransformHandle = gl->getUniformLocation(program, "uPrevTransform"); + transformHandle = gl->getUniformLocation(program, "uTransform"); + velCenterHandle = gl->getUniformLocation(program, "uVelCenter"); + maxDistanceHandle = gl->getUniformLocation(program, "maxDistance"); } bool MotionBlurFilter::updateLayer(Layer* targetLayer, Frame layerFrame) { - auto contentFrame = layerFrame - targetLayer->startTime; - auto layerCache = LayerCache::Get(targetLayer); - previousMatrix = layerCache->getTransform(contentFrame > 0 ? contentFrame - 1 : 0)->matrix; - currentMatrix = layerCache->getTransform(contentFrame)->matrix; - return previousMatrix != currentMatrix; + auto contentFrame = layerFrame - targetLayer->startTime; + auto layerCache = LayerCache::Get(targetLayer); + previousMatrix = layerCache->getTransform(contentFrame > 0 ? contentFrame - 1 : 0)->matrix; + currentMatrix = layerCache->getTransform(contentFrame)->matrix; + return previousMatrix != currentMatrix; } void MotionBlurFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, const Point&) { - auto width = static_cast(contentBounds.width()); - auto height = static_cast(contentBounds.height()); - auto origin = ImageOrigin::BottomLeft; - - previousMatrix.preTranslate(contentBounds.left, contentBounds.top); - currentMatrix.preTranslate(contentBounds.left, contentBounds.top); - std::array previousGLMatrix = ToGLTextureMatrix(previousMatrix, width, height, origin); - std::array currentGLMatrix = ToGLTextureMatrix(currentMatrix, width, height, origin); - - auto scaling = (previousMatrix.getScaleX() != currentMatrix.getScaleX() || - previousMatrix.getScaleY() != currentMatrix.getScaleY()); - - gl->uniformMatrix3fv(prevTransformHandle, 1, GL::FALSE, previousGLMatrix.data()); - gl->uniformMatrix3fv(transformHandle, 1, GL::FALSE, currentGLMatrix.data()); - gl->uniform1f(velCenterHandle, scaling ? 0.0f : 0.5f); - gl->uniform1f(maxDistanceHandle, (MOTION_BLUR_SCALE_FACTOR - 1.0) * 0.5f); + auto width = static_cast(contentBounds.width()); + auto height = static_cast(contentBounds.height()); + auto origin = ImageOrigin::BottomLeft; + + previousMatrix.preTranslate(contentBounds.left, contentBounds.top); + currentMatrix.preTranslate(contentBounds.left, contentBounds.top); + std::array previousGLMatrix = ToGLTextureMatrix(previousMatrix, width, height, origin); + std::array currentGLMatrix = ToGLTextureMatrix(currentMatrix, width, height, origin); + + auto scaling = (previousMatrix.getScaleX() != currentMatrix.getScaleX() || + previousMatrix.getScaleY() != currentMatrix.getScaleY()); + + gl->uniformMatrix3fv(prevTransformHandle, 1, GL::FALSE, previousGLMatrix.data()); + gl->uniformMatrix3fv(transformHandle, 1, GL::FALSE, currentGLMatrix.data()); + gl->uniform1f(velCenterHandle, scaling ? 0.0f : 0.5f); + gl->uniform1f(maxDistanceHandle, (MOTION_BLUR_SCALE_FACTOR - 1.0) * 0.5f); } std::vector MotionBlurFilter::computeVertices(const Rect& inputBounds, - const Rect& outputBounds, const Point&) { - return ComputeVerticesForMotionBlurAndBulge(inputBounds, outputBounds); + const Rect& outputBounds, const Point&) { + return ComputeVerticesForMotionBlurAndBulge(inputBounds, outputBounds); } } // namespace pag diff --git a/src/rendering/filters/MotionBlurFilter.h b/src/rendering/filters/MotionBlurFilter.h index 607d68ac9a..f657e3546a 100644 --- a/src/rendering/filters/MotionBlurFilter.h +++ b/src/rendering/filters/MotionBlurFilter.h @@ -22,35 +22,35 @@ namespace pag { class MotionBlurFilter : public LayerFilter { - public: - static void TransformBounds(Rect* bounds, const Point& filterScale, Layer* layer, - Frame layerFrame); +public: + static void TransformBounds(Rect* bounds, const Point& filterScale, Layer* layer, + Frame layerFrame); - MotionBlurFilter(); - ~MotionBlurFilter() override = default; + MotionBlurFilter(); + ~MotionBlurFilter() override = default; - bool updateLayer(Layer* layer, Frame layerFrame); + bool updateLayer(Layer* layer, Frame layerFrame); - protected: - std::string onBuildVertexShader() override; +protected: + std::string onBuildVertexShader() override; - std::string onBuildFragmentShader() override; + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - private: - Matrix previousMatrix = Matrix::I(); - Matrix currentMatrix = Matrix::I(); +private: + Matrix previousMatrix = Matrix::I(); + Matrix currentMatrix = Matrix::I(); - int prevTransformHandle = 0; - int transformHandle = 0; - int velCenterHandle = 0; - int maxDistanceHandle = 0; + int prevTransformHandle = 0; + int transformHandle = 0; + int velCenterHandle = 0; + int maxDistanceHandle = 0; }; } // namespace pag diff --git a/src/rendering/filters/MotionTileFilter.cpp b/src/rendering/filters/MotionTileFilter.cpp index 24d489ac8c..41ce1dfc54 100644 --- a/src/rendering/filters/MotionTileFilter.cpp +++ b/src/rendering/filters/MotionTileFilter.cpp @@ -92,44 +92,44 @@ MotionTileFilter::MotionTileFilter(Effect* effect) : effect(effect) { } std::string MotionTileFilter::onBuildVertexShader() { - return MOTIONTILE_VERTEX_SHADER; + return MOTIONTILE_VERTEX_SHADER; } std::string MotionTileFilter::onBuildFragmentShader() { - return MOTIONTILE_FRAGMENT_SHADER; + return MOTIONTILE_FRAGMENT_SHADER; } void MotionTileFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - tileCenterHandle = gl->getUniformLocation(program, "uTileCenter"); - tileWidthHandle = gl->getUniformLocation(program, "uTileWidth"); - tileHeightHandle = gl->getUniformLocation(program, "uTileHeight"); - outputWidthHandle = gl->getUniformLocation(program, "uOutputWidth"); - outputHeightHandle = gl->getUniformLocation(program, "uOutputHeight"); - mirrorEdgesHandle = gl->getUniformLocation(program, "uMirrorEdges"); - phaseHandle = gl->getUniformLocation(program, "uPhase"); - isHorizontalPhaseShiftHandle = gl->getUniformLocation(program, "uIsHorizontalPhaseShift"); + tileCenterHandle = gl->getUniformLocation(program, "uTileCenter"); + tileWidthHandle = gl->getUniformLocation(program, "uTileWidth"); + tileHeightHandle = gl->getUniformLocation(program, "uTileHeight"); + outputWidthHandle = gl->getUniformLocation(program, "uOutputWidth"); + outputHeightHandle = gl->getUniformLocation(program, "uOutputHeight"); + mirrorEdgesHandle = gl->getUniformLocation(program, "uMirrorEdges"); + phaseHandle = gl->getUniformLocation(program, "uPhase"); + isHorizontalPhaseShiftHandle = gl->getUniformLocation(program, "uIsHorizontalPhaseShift"); } void MotionTileFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, const Point&) { - auto* pagEffect = reinterpret_cast(effect); - auto tileCenter = pagEffect->tileCenter->getValueAt(layerFrame); - auto tileWidth = pagEffect->tileWidth->getValueAt(layerFrame); - auto tileHeight = pagEffect->tileHeight->getValueAt(layerFrame); - auto outputWidth = pagEffect->outputWidth->getValueAt(layerFrame); - auto outputHeight = pagEffect->outputHeight->getValueAt(layerFrame); - auto mirrorEdges = pagEffect->mirrorEdges->getValueAt(layerFrame); - auto phase = pagEffect->phase->getValueAt(layerFrame); - auto isHorizontalPhaseShift = pagEffect->horizontalPhaseShift->getValueAt(layerFrame); - - gl->uniform2f(tileCenterHandle, (tileCenter.x - contentBounds.x()) / contentBounds.width(), - 1.0f - (tileCenter.y - contentBounds.y()) / contentBounds.height()); - gl->uniform1f(tileWidthHandle, tileWidth / 100.f); - gl->uniform1f(tileHeightHandle, tileHeight / 100.f); - gl->uniform1f(outputWidthHandle, outputWidth / 100.f); - gl->uniform1f(outputHeightHandle, outputHeight / 100.f); - gl->uniform1i(mirrorEdgesHandle, mirrorEdges); - gl->uniform1f(phaseHandle, phase); - gl->uniform1i(isHorizontalPhaseShiftHandle, isHorizontalPhaseShift); + auto* pagEffect = reinterpret_cast(effect); + auto tileCenter = pagEffect->tileCenter->getValueAt(layerFrame); + auto tileWidth = pagEffect->tileWidth->getValueAt(layerFrame); + auto tileHeight = pagEffect->tileHeight->getValueAt(layerFrame); + auto outputWidth = pagEffect->outputWidth->getValueAt(layerFrame); + auto outputHeight = pagEffect->outputHeight->getValueAt(layerFrame); + auto mirrorEdges = pagEffect->mirrorEdges->getValueAt(layerFrame); + auto phase = pagEffect->phase->getValueAt(layerFrame); + auto isHorizontalPhaseShift = pagEffect->horizontalPhaseShift->getValueAt(layerFrame); + + gl->uniform2f(tileCenterHandle, (tileCenter.x - contentBounds.x()) / contentBounds.width(), + 1.0f - (tileCenter.y - contentBounds.y()) / contentBounds.height()); + gl->uniform1f(tileWidthHandle, tileWidth / 100.f); + gl->uniform1f(tileHeightHandle, tileHeight / 100.f); + gl->uniform1f(outputWidthHandle, outputWidth / 100.f); + gl->uniform1f(outputHeightHandle, outputHeight / 100.f); + gl->uniform1i(mirrorEdgesHandle, mirrorEdges); + gl->uniform1f(phaseHandle, phase); + gl->uniform1i(isHorizontalPhaseShiftHandle, isHorizontalPhaseShift); } } // namespace pag diff --git a/src/rendering/filters/MotionTileFilter.h b/src/rendering/filters/MotionTileFilter.h index 4dfc928283..05c1e8c7cd 100644 --- a/src/rendering/filters/MotionTileFilter.h +++ b/src/rendering/filters/MotionTileFilter.h @@ -22,30 +22,30 @@ namespace pag { class MotionTileFilter : public LayerFilter { - public: - explicit MotionTileFilter(Effect* effect); - ~MotionTileFilter() override = default; +public: + explicit MotionTileFilter(Effect* effect); + ~MotionTileFilter() override = default; - protected: - std::string onBuildVertexShader() override; +protected: + std::string onBuildVertexShader() override; - std::string onBuildFragmentShader() override; + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - int tileCenterHandle = 0; - int tileWidthHandle = 0; - int tileHeightHandle = 0; - int outputWidthHandle = 0; - int outputHeightHandle = 0; - int mirrorEdgesHandle = 0; - int phaseHandle = 0; - int isHorizontalPhaseShiftHandle = 0; + int tileCenterHandle = 0; + int tileWidthHandle = 0; + int tileHeightHandle = 0; + int outputWidthHandle = 0; + int outputHeightHandle = 0; + int mirrorEdgesHandle = 0; + int phaseHandle = 0; + int isHorizontalPhaseShiftHandle = 0; }; } // namespace pag diff --git a/src/rendering/filters/RadialBlurFilter.cpp b/src/rendering/filters/RadialBlurFilter.cpp index 17056db4bd..72cc0a6f5b 100644 --- a/src/rendering/filters/RadialBlurFilter.cpp +++ b/src/rendering/filters/RadialBlurFilter.cpp @@ -59,24 +59,24 @@ RadialBlurFilter::RadialBlurFilter(Effect* effect) : effect(effect) { } std::string RadialBlurFilter::onBuildFragmentShader() { - return RADIAL_BLUR_FRAGMENT_SHADER; + return RADIAL_BLUR_FRAGMENT_SHADER; } void RadialBlurFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - amountHandle = gl->getUniformLocation(program, "uAmount"); - centerHandle = gl->getUniformLocation(program, "uCenter"); + amountHandle = gl->getUniformLocation(program, "uAmount"); + centerHandle = gl->getUniformLocation(program, "uCenter"); } void RadialBlurFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, const Point&) { - auto* radialBlurEffect = reinterpret_cast(effect); - auto amount = radialBlurEffect->amount->getValueAt(layerFrame) * 0.00625; - auto center = radialBlurEffect->center->getValueAt(layerFrame); + auto* radialBlurEffect = reinterpret_cast(effect); + auto amount = radialBlurEffect->amount->getValueAt(layerFrame) * 0.00625; + auto center = radialBlurEffect->center->getValueAt(layerFrame); - amount = amount < 0.25 ? amount : 0.25; + amount = amount < 0.25 ? amount : 0.25; - gl->uniform1f(amountHandle, amount); - gl->uniform2f(centerHandle, (center.x - contentBounds.x()) / contentBounds.width(), - (center.y - contentBounds.y()) / contentBounds.height()); + gl->uniform1f(amountHandle, amount); + gl->uniform2f(centerHandle, (center.x - contentBounds.x()) / contentBounds.width(), + (center.y - contentBounds.y()) / contentBounds.height()); } } // namespace pag diff --git a/src/rendering/filters/RadialBlurFilter.h b/src/rendering/filters/RadialBlurFilter.h index aeecab4732..1c489ade3c 100644 --- a/src/rendering/filters/RadialBlurFilter.h +++ b/src/rendering/filters/RadialBlurFilter.h @@ -22,22 +22,22 @@ namespace pag { class RadialBlurFilter : public LayerFilter { - public: - explicit RadialBlurFilter(Effect* effect); - ~RadialBlurFilter() override = default; +public: + explicit RadialBlurFilter(Effect* effect); + ~RadialBlurFilter() override = default; - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - int amountHandle = -1; - int centerHandle = -1; + int amountHandle = -1; + int centerHandle = -1; }; } // namespace pag diff --git a/src/rendering/filters/dropshadow/DropShadowFilter.cpp b/src/rendering/filters/dropshadow/DropShadowFilter.cpp index deddeaa001..4fb7810fa6 100644 --- a/src/rendering/filters/dropshadow/DropShadowFilter.cpp +++ b/src/rendering/filters/dropshadow/DropShadowFilter.cpp @@ -23,241 +23,241 @@ namespace pag { DropShadowFilter::DropShadowFilter(DropShadowStyle* layerStyle) : layerStyle(layerStyle) { - blurFilterV = new SinglePassBlurFilter(BlurDirection::Vertical); - blurFilterH = new SinglePassBlurFilter(BlurDirection::Horizontal); - spreadFilter = new DropShadowSpreadFilter(layerStyle, DropShadowStyleMode::Normal); - spreadThickFilter = new DropShadowSpreadFilter(layerStyle, DropShadowStyleMode::Thick); + blurFilterV = new SinglePassBlurFilter(BlurDirection::Vertical); + blurFilterH = new SinglePassBlurFilter(BlurDirection::Horizontal); + spreadFilter = new DropShadowSpreadFilter(layerStyle, DropShadowStyleMode::Normal); + spreadThickFilter = new DropShadowSpreadFilter(layerStyle, DropShadowStyleMode::Thick); } DropShadowFilter::~DropShadowFilter() { - delete blurFilterV; - delete blurFilterH; - delete spreadFilter; - delete spreadThickFilter; + delete blurFilterV; + delete blurFilterH; + delete spreadFilter; + delete spreadThickFilter; } bool DropShadowFilter::initialize(Context* context) { - if (!blurFilterV->initialize(context)) { - return false; - } - if (!blurFilterH->initialize(context)) { - return false; - } - if (!spreadFilter->initialize(context)) { - return false; - } - if (!spreadThickFilter->initialize(context)) { - return false; - } - return true; + if (!blurFilterV->initialize(context)) { + return false; + } + if (!blurFilterH->initialize(context)) { + return false; + } + if (!spreadFilter->initialize(context)) { + return false; + } + if (!spreadThickFilter->initialize(context)) { + return false; + } + return true; } void DropShadowFilter::update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, const Point& filterScale) { - LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); + LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); - color = layerStyle->color->getValueAt(layerFrame); - opacity = layerStyle->opacity->getValueAt(layerFrame); - spread = layerStyle->spread->getValueAt(layerFrame); - auto size = layerStyle->size->getValueAt(layerFrame); - spread *= (spread == 1.0) ? 1.0 : 0.8; - blurSize = (1.0f - spread) * size; - spreadSize = size * spread; + color = layerStyle->color->getValueAt(layerFrame); + opacity = layerStyle->opacity->getValueAt(layerFrame); + spread = layerStyle->spread->getValueAt(layerFrame); + auto size = layerStyle->size->getValueAt(layerFrame); + spread *= (spread == 1.0) ? 1.0 : 0.8; + blurSize = (1.0f - spread) * size; + spreadSize = size * spread; - filtersBounds.clear(); - filtersBounds.emplace_back(contentBounds); - if (spread == 0.0f) { - updateParamModeNotSpread(frame, contentBounds, transformedBounds, filterScale); - } else if (spread == 1.0f) { - updateParamModeFullSpread(frame, contentBounds, transformedBounds, filterScale); - } else { - updateParamModeNotFullSpread(frame, contentBounds, transformedBounds, filterScale); - } + filtersBounds.clear(); + filtersBounds.emplace_back(contentBounds); + if (spread == 0.0f) { + updateParamModeNotSpread(frame, contentBounds, transformedBounds, filterScale); + } else if (spread == 1.0f) { + updateParamModeFullSpread(frame, contentBounds, transformedBounds, filterScale); + } else { + updateParamModeNotFullSpread(frame, contentBounds, transformedBounds, filterScale); + } } void DropShadowFilter::draw(Context* context, const FilterSource* source, const FilterTarget* target) { - if (source == nullptr || target == nullptr) { - return; - } - if (spread == 0.0) { - onDrawModeNotSpread(context, source, target); - } else if (spread == 1.0) { - onDrawModeFullSpread(context, source, target); - } else { - onDrawModeNotFullSpread(context, source, target); - } + if (source == nullptr || target == nullptr) { + return; + } + if (spread == 0.0) { + onDrawModeNotSpread(context, source, target); + } else if (spread == 1.0) { + onDrawModeFullSpread(context, source, target); + } else { + onDrawModeNotFullSpread(context, source, target); + } } void DropShadowFilter::updateParamModeNotSpread(Frame frame, const Rect& contentBounds, const Rect&, - const Point& filterScale) { - auto angle = layerStyle->angle->getValueAt(layerFrame); - auto distance = layerStyle->distance->getValueAt(layerFrame); - auto radians = DegreesToRadians(angle - 180); - float offsetY = -sinf(radians) * distance; - float offsetX = cosf(radians) * distance; + const Point& filterScale) { + auto angle = layerStyle->angle->getValueAt(layerFrame); + auto distance = layerStyle->distance->getValueAt(layerFrame); + auto radians = DegreesToRadians(angle - 180); + float offsetY = -sinf(radians) * distance; + float offsetX = cosf(radians) * distance; - auto filterVBounds = contentBounds; - filterVBounds.offset(0, offsetY * filterScale.y); - filterVBounds.outset(0, blurSize * filterScale.y); - filterVBounds.roundOut(); - blurFilterV->update(frame, contentBounds, filterVBounds, filterScale); - filtersBounds.emplace_back(filterVBounds); - auto filterHBounds = filterVBounds; - filterHBounds.offset(offsetX * filterScale.x, 0); - filterHBounds.outset(blurSize * filterScale.x, 0); - filterHBounds.roundOut(); - blurFilterH->update(frame, filterVBounds, filterHBounds, filterScale); - filtersBounds.emplace_back(filterHBounds); + auto filterVBounds = contentBounds; + filterVBounds.offset(0, offsetY * filterScale.y); + filterVBounds.outset(0, blurSize * filterScale.y); + filterVBounds.roundOut(); + blurFilterV->update(frame, contentBounds, filterVBounds, filterScale); + filtersBounds.emplace_back(filterVBounds); + auto filterHBounds = filterVBounds; + filterHBounds.offset(offsetX * filterScale.x, 0); + filterHBounds.outset(blurSize * filterScale.x, 0); + filterHBounds.roundOut(); + blurFilterH->update(frame, filterVBounds, filterHBounds, filterScale); + filtersBounds.emplace_back(filterHBounds); } void DropShadowFilter::updateParamModeNotFullSpread(Frame frame, const Rect& contentBounds, - const Rect&, const Point& filterScale) { - auto angle = layerStyle->angle->getValueAt(layerFrame); - auto distance = layerStyle->distance->getValueAt(layerFrame); - auto radians = DegreesToRadians(angle - 180); - float offsetY = -sinf(radians) * distance; - float offsetX = cosf(radians) * distance; + const Rect&, const Point& filterScale) { + auto angle = layerStyle->angle->getValueAt(layerFrame); + auto distance = layerStyle->distance->getValueAt(layerFrame); + auto radians = DegreesToRadians(angle - 180); + float offsetY = -sinf(radians) * distance; + float offsetX = cosf(radians) * distance; - auto filterBounds = contentBounds; - filterBounds.outset(spreadSize * filterScale.x, spreadSize * filterScale.y); - filterBounds.roundOut(); - if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { - spreadFilter->update(frame, contentBounds, filterBounds, filterScale); - } else { - spreadThickFilter->update(frame, contentBounds, filterBounds, filterScale); - } - filtersBounds.emplace_back(filterBounds); - auto lastBounds = filterBounds; - filterBounds.offset(0, offsetY * filterScale.y); - filterBounds.outset(0, blurSize * filterScale.y); - blurFilterV->update(frame, lastBounds, filterBounds, filterScale); - filterBounds.roundOut(); - filtersBounds.emplace_back(filterBounds); - lastBounds = filterBounds; - filterBounds.offset(offsetX * filterScale.x, 0); - filterBounds.outset(blurSize * filterScale.x, 0); - blurFilterH->update(frame, lastBounds, filterBounds, filterScale); - filtersBounds.emplace_back(filterBounds); + auto filterBounds = contentBounds; + filterBounds.outset(spreadSize * filterScale.x, spreadSize * filterScale.y); + filterBounds.roundOut(); + if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { + spreadFilter->update(frame, contentBounds, filterBounds, filterScale); + } else { + spreadThickFilter->update(frame, contentBounds, filterBounds, filterScale); + } + filtersBounds.emplace_back(filterBounds); + auto lastBounds = filterBounds; + filterBounds.offset(0, offsetY * filterScale.y); + filterBounds.outset(0, blurSize * filterScale.y); + blurFilterV->update(frame, lastBounds, filterBounds, filterScale); + filterBounds.roundOut(); + filtersBounds.emplace_back(filterBounds); + lastBounds = filterBounds; + filterBounds.offset(offsetX * filterScale.x, 0); + filterBounds.outset(blurSize * filterScale.x, 0); + blurFilterH->update(frame, lastBounds, filterBounds, filterScale); + filtersBounds.emplace_back(filterBounds); } void DropShadowFilter::updateParamModeFullSpread(Frame frame, const Rect& contentBounds, - const Rect&, const Point& filterScale) { - auto angle = layerStyle->angle->getValueAt(layerFrame); - auto distance = layerStyle->distance->getValueAt(layerFrame); - auto radians = DegreesToRadians(angle - 180); - float offsetY = -sinf(radians) * distance; - float offsetX = cosf(radians) * distance; + const Rect&, const Point& filterScale) { + auto angle = layerStyle->angle->getValueAt(layerFrame); + auto distance = layerStyle->distance->getValueAt(layerFrame); + auto radians = DegreesToRadians(angle - 180); + float offsetY = -sinf(radians) * distance; + float offsetX = cosf(radians) * distance; - auto filterBounds = contentBounds; - filterBounds.outset(spreadSize * filterScale.x, spreadSize * filterScale.y); - filterBounds.offset(offsetX * filterScale.x, offsetY * filterScale.y); - filterBounds.roundOut(); - if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { - spreadFilter->update(frame, contentBounds, filterBounds, filterScale); - } else { - spreadThickFilter->update(frame, contentBounds, filterBounds, filterScale); - } - filtersBounds.emplace_back(filterBounds); + auto filterBounds = contentBounds; + filterBounds.outset(spreadSize * filterScale.x, spreadSize * filterScale.y); + filterBounds.offset(offsetX * filterScale.x, offsetY * filterScale.y); + filterBounds.roundOut(); + if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { + spreadFilter->update(frame, contentBounds, filterBounds, filterScale); + } else { + spreadThickFilter->update(frame, contentBounds, filterBounds, filterScale); + } + filtersBounds.emplace_back(filterBounds); } void DropShadowFilter::onDrawModeNotSpread(Context* context, const FilterSource* source, - const FilterTarget* target) { - auto contentBounds = filtersBounds[0]; - auto filterBounds = filtersBounds[1]; - auto targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); - auto targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); - if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || - blurFilterBuffer->height() != targetHeight) { - blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); - } - if (blurFilterBuffer == nullptr) { - return; - } - auto gl = GLContext::Unwrap(context); - blurFilterBuffer->clearColor(gl); + const FilterTarget* target) { + auto contentBounds = filtersBounds[0]; + auto filterBounds = filtersBounds[1]; + auto targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); + auto targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); + if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || + blurFilterBuffer->height() != targetHeight) { + blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); + } + if (blurFilterBuffer == nullptr) { + return; + } + auto gl = GLContext::Unwrap(context); + blurFilterBuffer->clearColor(gl); - auto offsetMatrix = Matrix::MakeTrans((contentBounds.left - filterBounds.left) * source->scale.x, - (contentBounds.top - filterBounds.top) * source->scale.y); - auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); + auto offsetMatrix = Matrix::MakeTrans((contentBounds.left - filterBounds.left) * source->scale.x, + (contentBounds.top - filterBounds.top) * source->scale.y); + auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); - blurFilterV->updateParams(blurSize, 1.0, false, BlurMode::Shadow); - blurFilterV->enableBlurColor(color); - blurFilterV->draw(context, source, targetV.get()); - blurFilterV->disableBlurColor(); + blurFilterV->updateParams(blurSize, 1.0, false, BlurMode::Shadow); + blurFilterV->enableBlurColor(color); + blurFilterV->draw(context, source, targetV.get()); + blurFilterV->disableBlurColor(); - auto sourceH = blurFilterBuffer->toFilterSource(source->scale); + auto sourceH = blurFilterBuffer->toFilterSource(source->scale); - blurFilterH->updateParams(blurSize, opacity / 255.f, false, BlurMode::Shadow); - Matrix revertMatrix = - Matrix::MakeTrans((filterBounds.left - contentBounds.left) * source->scale.x, - (filterBounds.top - contentBounds.top) * source->scale.y); + blurFilterH->updateParams(blurSize, opacity / 255.f, false, BlurMode::Shadow); + Matrix revertMatrix = + Matrix::MakeTrans((filterBounds.left - contentBounds.left) * source->scale.x, + (filterBounds.top - contentBounds.top) * source->scale.y); - auto targetH = *target; - PreConcatMatrix(&targetH, revertMatrix); - blurFilterH->draw(context, sourceH.get(), &targetH); + auto targetH = *target; + PreConcatMatrix(&targetH, revertMatrix); + blurFilterH->draw(context, sourceH.get(), &targetH); } void DropShadowFilter::onDrawModeNotFullSpread(Context* context, const FilterSource* source, - const FilterTarget* target) { - auto contentBounds = filtersBounds[0]; - auto lastBounds = contentBounds; - auto filterBounds = filtersBounds[1]; - auto targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); - auto targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); - if (spreadFilterBuffer == nullptr || spreadFilterBuffer->width() != targetWidth || - spreadFilterBuffer->height() != targetHeight) { - spreadFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); - } - if (spreadFilterBuffer == nullptr) { - return; - } - auto gl = GLContext::Unwrap(context); - spreadFilterBuffer->clearColor(gl); - auto offsetMatrix = Matrix::MakeTrans((lastBounds.left - filterBounds.left) * source->scale.x, - (lastBounds.top - filterBounds.top) * source->scale.y); - auto targetSpread = spreadFilterBuffer->toFilterTarget(offsetMatrix); - if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { - spreadFilter->draw(context, source, targetSpread.get()); - } else { - spreadThickFilter->draw(context, source, targetSpread.get()); - } + const FilterTarget* target) { + auto contentBounds = filtersBounds[0]; + auto lastBounds = contentBounds; + auto filterBounds = filtersBounds[1]; + auto targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); + auto targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); + if (spreadFilterBuffer == nullptr || spreadFilterBuffer->width() != targetWidth || + spreadFilterBuffer->height() != targetHeight) { + spreadFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); + } + if (spreadFilterBuffer == nullptr) { + return; + } + auto gl = GLContext::Unwrap(context); + spreadFilterBuffer->clearColor(gl); + auto offsetMatrix = Matrix::MakeTrans((lastBounds.left - filterBounds.left) * source->scale.x, + (lastBounds.top - filterBounds.top) * source->scale.y); + auto targetSpread = spreadFilterBuffer->toFilterTarget(offsetMatrix); + if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { + spreadFilter->draw(context, source, targetSpread.get()); + } else { + spreadThickFilter->draw(context, source, targetSpread.get()); + } - auto sourceV = spreadFilterBuffer->toFilterSource(source->scale); - lastBounds = filterBounds; - filterBounds = filtersBounds[2]; - targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); - targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); - if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || - blurFilterBuffer->height() != targetHeight) { - blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); - } - if (blurFilterBuffer == nullptr) { - return; - } - blurFilterBuffer->clearColor(gl); - offsetMatrix = Matrix::MakeTrans((lastBounds.left - filterBounds.left) * source->scale.x, - (lastBounds.top - filterBounds.top) * source->scale.y); - auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); - blurFilterV->updateParams(blurSize, 1.0, false, BlurMode::Shadow); - blurFilterV->draw(context, sourceV.get(), targetV.get()); + auto sourceV = spreadFilterBuffer->toFilterSource(source->scale); + lastBounds = filterBounds; + filterBounds = filtersBounds[2]; + targetWidth = static_cast(ceilf(filterBounds.width() * source->scale.x)); + targetHeight = static_cast(ceilf(filterBounds.height() * source->scale.y)); + if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || + blurFilterBuffer->height() != targetHeight) { + blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); + } + if (blurFilterBuffer == nullptr) { + return; + } + blurFilterBuffer->clearColor(gl); + offsetMatrix = Matrix::MakeTrans((lastBounds.left - filterBounds.left) * source->scale.x, + (lastBounds.top - filterBounds.top) * source->scale.y); + auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); + blurFilterV->updateParams(blurSize, 1.0, false, BlurMode::Shadow); + blurFilterV->draw(context, sourceV.get(), targetV.get()); - auto sourceH = blurFilterBuffer->toFilterSource(source->scale); - Matrix revertMatrix = - Matrix::MakeTrans((filterBounds.left - contentBounds.left) * source->scale.x, - (filterBounds.top - contentBounds.top) * source->scale.y); - auto targetH = *target; - PreConcatMatrix(&targetH, revertMatrix); - blurFilterH->updateParams(blurSize, opacity / 255.f, false, BlurMode::Shadow); - blurFilterH->draw(context, sourceH.get(), &targetH); + auto sourceH = blurFilterBuffer->toFilterSource(source->scale); + Matrix revertMatrix = + Matrix::MakeTrans((filterBounds.left - contentBounds.left) * source->scale.x, + (filterBounds.top - contentBounds.top) * source->scale.y); + auto targetH = *target; + PreConcatMatrix(&targetH, revertMatrix); + blurFilterH->updateParams(blurSize, opacity / 255.f, false, BlurMode::Shadow); + blurFilterH->draw(context, sourceH.get(), &targetH); } void DropShadowFilter::onDrawModeFullSpread(Context* context, const FilterSource* source, - const FilterTarget* target) { - if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { - spreadFilter->draw(context, source, target); - } else { - spreadThickFilter->draw(context, source, target); - } + const FilterTarget* target) { + if (spreadSize < DROPSHADOW_SPREAD_MIN_THICK_SIZE) { + spreadFilter->draw(context, source, target); + } else { + spreadThickFilter->draw(context, source, target); + } } } // namespace pag diff --git a/src/rendering/filters/dropshadow/DropShadowFilter.h b/src/rendering/filters/dropshadow/DropShadowFilter.h index f14814c222..f0f118535d 100644 --- a/src/rendering/filters/dropshadow/DropShadowFilter.h +++ b/src/rendering/filters/dropshadow/DropShadowFilter.h @@ -25,47 +25,47 @@ namespace pag { class DropShadowFilter : public LayerFilter { - public: - explicit DropShadowFilter(DropShadowStyle* layerStyle); - ~DropShadowFilter() override; +public: + explicit DropShadowFilter(DropShadowStyle* layerStyle); + ~DropShadowFilter() override; - bool initialize(Context* context) override; + bool initialize(Context* context) override; - void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; + void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; - private: - DropShadowStyle* layerStyle = nullptr; +private: + DropShadowStyle* layerStyle = nullptr; - std::shared_ptr spreadFilterBuffer = nullptr; - std::shared_ptr blurFilterBuffer = nullptr; + std::shared_ptr spreadFilterBuffer = nullptr; + std::shared_ptr blurFilterBuffer = nullptr; - SinglePassBlurFilter* blurFilterV = nullptr; - SinglePassBlurFilter* blurFilterH = nullptr; - DropShadowSpreadFilter* spreadFilter = nullptr; - DropShadowSpreadFilter* spreadThickFilter = nullptr; + SinglePassBlurFilter* blurFilterV = nullptr; + SinglePassBlurFilter* blurFilterH = nullptr; + DropShadowSpreadFilter* spreadFilter = nullptr; + DropShadowSpreadFilter* spreadThickFilter = nullptr; - Color color = Black; - float opacity = 0.0f; - float spread = 0.0f; - float spreadSize = 0.0f; - float blurSize = 0.0f; - std::vector filtersBounds = {}; + Color color = Black; + float opacity = 0.0f; + float spread = 0.0f; + float spreadSize = 0.0f; + float blurSize = 0.0f; + std::vector filtersBounds = {}; - void updateParamModeNotSpread(Frame frame, const Rect& contentBounds, - const Rect& transformedBounds, const Point& filterScale); - void updateParamModeNotFullSpread(Frame frame, const Rect& contentBounds, - const Rect& transformedBounds, const Point& filterScale); - void updateParamModeFullSpread(Frame frame, const Rect& contentBounds, - const Rect& transformedBounds, const Point& filterScale); + void updateParamModeNotSpread(Frame frame, const Rect& contentBounds, + const Rect& transformedBounds, const Point& filterScale); + void updateParamModeNotFullSpread(Frame frame, const Rect& contentBounds, + const Rect& transformedBounds, const Point& filterScale); + void updateParamModeFullSpread(Frame frame, const Rect& contentBounds, + const Rect& transformedBounds, const Point& filterScale); - void onDrawModeNotSpread(Context* context, const FilterSource* source, - const FilterTarget* target); - void onDrawModeNotFullSpread(Context* context, const FilterSource* source, - const FilterTarget* target); - void onDrawModeFullSpread(Context* context, const FilterSource* source, - const FilterTarget* target); + void onDrawModeNotSpread(Context* context, const FilterSource* source, + const FilterTarget* target); + void onDrawModeNotFullSpread(Context* context, const FilterSource* source, + const FilterTarget* target); + void onDrawModeFullSpread(Context* context, const FilterSource* source, + const FilterTarget* target); }; } // namespace pag diff --git a/src/rendering/filters/dropshadow/DropShadowSpreadFilter.cpp b/src/rendering/filters/dropshadow/DropShadowSpreadFilter.cpp index 9c113cfb6a..66d0173ff1 100644 --- a/src/rendering/filters/dropshadow/DropShadowSpreadFilter.cpp +++ b/src/rendering/filters/dropshadow/DropShadowSpreadFilter.cpp @@ -82,58 +82,60 @@ DropShadowSpreadFilter::DropShadowSpreadFilter(DropShadowStyle* style, DropShado } std::string DropShadowSpreadFilter::onBuildFragmentShader() { - if (styleMode == DropShadowStyleMode::Thick) { - return DROPSHADOW_SPREAD_THICK_FRAGMENT_SHADER; - } - return DROPSHADOW_SPREAD_FRAGMENT_SHADER; + if (styleMode == DropShadowStyleMode::Thick) { + return DROPSHADOW_SPREAD_THICK_FRAGMENT_SHADER; + } + return DROPSHADOW_SPREAD_FRAGMENT_SHADER; } void DropShadowSpreadFilter::onPrepareProgram(const GLInterface* gl, unsigned program) { - spreadColorHandle = gl->getUniformLocation(program, "uColor"); - spreadOpacityHandle = gl->getUniformLocation(program, "uOpacity"); - spreadSizeHandle = gl->getUniformLocation(program, "uSize"); + spreadColorHandle = gl->getUniformLocation(program, "uColor"); + spreadOpacityHandle = gl->getUniformLocation(program, "uOpacity"); + spreadSizeHandle = gl->getUniformLocation(program, "uSize"); } void DropShadowSpreadFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) { - auto color = layerStyle->color->getValueAt(layerFrame); - auto opacity = layerStyle->opacity->getValueAt(layerFrame); - auto spread = layerStyle->spread->getValueAt(layerFrame); - auto size = layerStyle->size->getValueAt(layerFrame); - spread *= (spread == 1.0) ? 1.0 : 0.8; - - auto spreadSizeX = size * spread * filterScale.x; - auto spreadSizeY = size * spread * filterScale.y; - spreadSizeX = std::min(spreadSizeX, DROPSHADOW_MAX_SPREAD_SIZE); - spreadSizeY = std::min(spreadSizeY, DROPSHADOW_MAX_SPREAD_SIZE); - - gl->uniform3f(spreadColorHandle, color.red / 255.f, color.green / 255.f, color.blue / 255.f); - gl->uniform1f(spreadOpacityHandle, opacity / 255.f); - gl->uniform2f(spreadSizeHandle, spreadSizeX / contentBounds.width(), - spreadSizeY / contentBounds.height()); + const Point& filterScale) { + auto color = layerStyle->color->getValueAt(layerFrame); + auto opacity = layerStyle->opacity->getValueAt(layerFrame); + auto spread = layerStyle->spread->getValueAt(layerFrame); + auto size = layerStyle->size->getValueAt(layerFrame); + spread *= (spread == 1.0) ? 1.0 : 0.8; + + auto spreadSizeX = size * spread * filterScale.x; + auto spreadSizeY = size * spread * filterScale.y; + spreadSizeX = std::min(spreadSizeX, DROPSHADOW_MAX_SPREAD_SIZE); + spreadSizeY = std::min(spreadSizeY, DROPSHADOW_MAX_SPREAD_SIZE); + + gl->uniform3f(spreadColorHandle, color.red / 255.f, color.green / 255.f, color.blue / 255.f); + gl->uniform1f(spreadOpacityHandle, opacity / 255.f); + gl->uniform2f(spreadSizeHandle, spreadSizeX / contentBounds.width(), + spreadSizeY / contentBounds.height()); } std::vector DropShadowSpreadFilter::computeVertices(const Rect&, const Rect& outputBounds, - const Point& filterScale) { - std::vector vertices = {}; - Point contentPoint[4] = {{outputBounds.left, outputBounds.bottom}, - {outputBounds.right, outputBounds.bottom}, - {outputBounds.left, outputBounds.top}, - {outputBounds.right, outputBounds.top}}; - - auto spread = layerStyle->spread->getValueAt(layerFrame); - auto size = layerStyle->size->getValueAt(layerFrame); - auto deltaX = -size * spread * filterScale.x; - auto deltaY = -size * spread * filterScale.y; - - Point texturePoints[4] = {{deltaX, (outputBounds.height() + deltaY)}, - {(outputBounds.width() + deltaX), (outputBounds.height() + deltaY)}, - {deltaX, deltaY}, - {(outputBounds.width() + deltaX), deltaY}}; - for (int ii = 0; ii < 4; ii++) { - vertices.push_back(contentPoint[ii]); - vertices.push_back(texturePoints[ii]); - } - return vertices; + const Point& filterScale) { + std::vector vertices = {}; + Point contentPoint[4] = {{outputBounds.left, outputBounds.bottom}, + {outputBounds.right, outputBounds.bottom}, + {outputBounds.left, outputBounds.top}, + {outputBounds.right, outputBounds.top} + }; + + auto spread = layerStyle->spread->getValueAt(layerFrame); + auto size = layerStyle->size->getValueAt(layerFrame); + auto deltaX = -size * spread * filterScale.x; + auto deltaY = -size * spread * filterScale.y; + + Point texturePoints[4] = {{deltaX, (outputBounds.height() + deltaY)}, + {(outputBounds.width() + deltaX), (outputBounds.height() + deltaY)}, + {deltaX, deltaY}, + {(outputBounds.width() + deltaX), deltaY} + }; + for (int ii = 0; ii < 4; ii++) { + vertices.push_back(contentPoint[ii]); + vertices.push_back(texturePoints[ii]); + } + return vertices; } } // namespace pag diff --git a/src/rendering/filters/dropshadow/DropShadowSpreadFilter.h b/src/rendering/filters/dropshadow/DropShadowSpreadFilter.h index a61e8c319b..5d0085178b 100644 --- a/src/rendering/filters/dropshadow/DropShadowSpreadFilter.h +++ b/src/rendering/filters/dropshadow/DropShadowSpreadFilter.h @@ -24,27 +24,27 @@ namespace pag { enum class DropShadowStyleMode { Normal, Thick }; class DropShadowSpreadFilter : public LayerFilter { - public: - explicit DropShadowSpreadFilter(DropShadowStyle* style, DropShadowStyleMode mode); - ~DropShadowSpreadFilter() override = default; +public: + explicit DropShadowSpreadFilter(DropShadowStyle* style, DropShadowStyleMode mode); + ~DropShadowSpreadFilter() override = default; - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - private: - DropShadowStyle* layerStyle = nullptr; - DropShadowStyleMode styleMode; +private: + DropShadowStyle* layerStyle = nullptr; + DropShadowStyleMode styleMode; - int spreadColorHandle = -1; - int spreadOpacityHandle = -1; - int spreadSizeHandle = -1; + int spreadColorHandle = -1; + int spreadOpacityHandle = -1; + int spreadSizeHandle = -1; }; } // namespace pag diff --git a/src/rendering/filters/gaussblur/GaussBlurFilter.cpp b/src/rendering/filters/gaussblur/GaussBlurFilter.cpp index 2b2f4f293a..3c92ffffbc 100644 --- a/src/rendering/filters/gaussblur/GaussBlurFilter.cpp +++ b/src/rendering/filters/gaussblur/GaussBlurFilter.cpp @@ -22,104 +22,104 @@ namespace pag { GaussBlurFilter::GaussBlurFilter(Effect* effect) : effect(effect) { - blurFilterV = new SinglePassBlurFilter(BlurDirection::Vertical); - blurFilterH = new SinglePassBlurFilter(BlurDirection::Horizontal); + blurFilterV = new SinglePassBlurFilter(BlurDirection::Vertical); + blurFilterH = new SinglePassBlurFilter(BlurDirection::Horizontal); } GaussBlurFilter::~GaussBlurFilter() { - delete blurFilterV; - delete blurFilterH; + delete blurFilterV; + delete blurFilterH; } bool GaussBlurFilter::initialize(Context* context) { - if (!blurFilterV->initialize(context)) { - return false; - } - if (!blurFilterH->initialize(context)) { - return false; - } - return true; + if (!blurFilterV->initialize(context)) { + return false; + } + if (!blurFilterH->initialize(context)) { + return false; + } + return true; } void GaussBlurFilter::update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, const Point& filterScale) { - LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); + LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); - auto* gaussBlurEffect = static_cast(effect); - repeatEdge = gaussBlurEffect->repeatEdgePixels->getValueAt(layerFrame); - blurDirection = - static_cast(gaussBlurEffect->blurDimensions->getValueAt(layerFrame)); - blurriness = gaussBlurEffect->blurriness->getValueAt(layerFrame); - auto expandY = blurriness * filterScale.y; - filtersBounds.clear(); - filtersBounds.emplace_back(contentBounds); - switch (blurDirection) { + auto* gaussBlurEffect = static_cast(effect); + repeatEdge = gaussBlurEffect->repeatEdgePixels->getValueAt(layerFrame); + blurDirection = + static_cast(gaussBlurEffect->blurDimensions->getValueAt(layerFrame)); + blurriness = gaussBlurEffect->blurriness->getValueAt(layerFrame); + auto expandY = blurriness * filterScale.y; + filtersBounds.clear(); + filtersBounds.emplace_back(contentBounds); + switch (blurDirection) { case BlurDirection::Vertical: - blurFilterV->update(frame, contentBounds, transformedBounds, filterScale); - break; + blurFilterV->update(frame, contentBounds, transformedBounds, filterScale); + break; case BlurDirection::Horizontal: - blurFilterH->update(frame, contentBounds, transformedBounds, filterScale); - break; + blurFilterH->update(frame, contentBounds, transformedBounds, filterScale); + break; case BlurDirection::Both: - auto blurVBounds = contentBounds; - if (!repeatEdge) { - blurVBounds.outset(0, expandY); - blurVBounds.roundOut(); - } - filtersBounds.emplace_back(blurVBounds); - blurFilterV->update(frame, contentBounds, blurVBounds, filterScale); - blurFilterH->update(frame, blurVBounds, transformedBounds, filterScale); - break; - } - filtersBounds.emplace_back(transformedBounds); + auto blurVBounds = contentBounds; + if (!repeatEdge) { + blurVBounds.outset(0, expandY); + blurVBounds.roundOut(); + } + filtersBounds.emplace_back(blurVBounds); + blurFilterV->update(frame, contentBounds, blurVBounds, filterScale); + blurFilterH->update(frame, blurVBounds, transformedBounds, filterScale); + break; + } + filtersBounds.emplace_back(transformedBounds); } void GaussBlurFilter::draw(Context* context, const FilterSource* source, const FilterTarget* target) { - if (source == nullptr || target == nullptr) { - LOGE("GaussFilter::draw() can not draw filter"); - return; - } - switch (blurDirection) { + if (source == nullptr || target == nullptr) { + LOGE("GaussFilter::draw() can not draw filter"); + return; + } + switch (blurDirection) { case BlurDirection::Vertical: - blurFilterV->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); - blurFilterV->draw(context, source, target); - break; + blurFilterV->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); + blurFilterV->draw(context, source, target); + break; case BlurDirection::Horizontal: - blurFilterH->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); - blurFilterH->draw(context, source, target); - break; + blurFilterH->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); + blurFilterH->draw(context, source, target); + break; case BlurDirection::Both: - blurFilterV->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); - auto contentBounds = filtersBounds[0]; - auto blurVBounds = filtersBounds[1]; - auto targetWidth = static_cast(ceilf(blurVBounds.width() * source->scale.x)); - auto targetHeight = static_cast(ceilf(blurVBounds.height() * source->scale.y)); - if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || - blurFilterBuffer->height() != targetHeight) { - blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); - } - if (blurFilterBuffer == nullptr) { - return; - } - auto gl = GLContext::Unwrap(context); - blurFilterBuffer->clearColor(gl); + blurFilterV->updateParams(blurriness, 1.0, repeatEdge, BlurMode::Picture); + auto contentBounds = filtersBounds[0]; + auto blurVBounds = filtersBounds[1]; + auto targetWidth = static_cast(ceilf(blurVBounds.width() * source->scale.x)); + auto targetHeight = static_cast(ceilf(blurVBounds.height() * source->scale.y)); + if (blurFilterBuffer == nullptr || blurFilterBuffer->width() != targetWidth || + blurFilterBuffer->height() != targetHeight) { + blurFilterBuffer = FilterBuffer::Make(context, targetWidth, targetHeight); + } + if (blurFilterBuffer == nullptr) { + return; + } + auto gl = GLContext::Unwrap(context); + blurFilterBuffer->clearColor(gl); - auto offsetMatrix = - Matrix::MakeTrans((contentBounds.left - blurVBounds.left) * source->scale.x, - (contentBounds.top - blurVBounds.top) * source->scale.y); - auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); - blurFilterV->draw(context, source, targetV.get()); + auto offsetMatrix = + Matrix::MakeTrans((contentBounds.left - blurVBounds.left) * source->scale.x, + (contentBounds.top - blurVBounds.top) * source->scale.y); + auto targetV = blurFilterBuffer->toFilterTarget(offsetMatrix); + blurFilterV->draw(context, source, targetV.get()); - auto sourceH = blurFilterBuffer->toFilterSource(source->scale); - blurFilterH->updateParams(blurriness, 1.0f, repeatEdge, BlurMode::Picture); - Matrix revertMatrix = - Matrix::MakeTrans((blurVBounds.left - contentBounds.left) * source->scale.x, - (blurVBounds.top - contentBounds.top) * source->scale.y); - auto targetH = *target; - PreConcatMatrix(&targetH, revertMatrix); - blurFilterH->draw(context, sourceH.get(), &targetH); - break; - } + auto sourceH = blurFilterBuffer->toFilterSource(source->scale); + blurFilterH->updateParams(blurriness, 1.0f, repeatEdge, BlurMode::Picture); + Matrix revertMatrix = + Matrix::MakeTrans((blurVBounds.left - contentBounds.left) * source->scale.x, + (blurVBounds.top - contentBounds.top) * source->scale.y); + auto targetH = *target; + PreConcatMatrix(&targetH, revertMatrix); + blurFilterH->draw(context, sourceH.get(), &targetH); + break; + } } } // namespace pag diff --git a/src/rendering/filters/gaussblur/GaussBlurFilter.h b/src/rendering/filters/gaussblur/GaussBlurFilter.h index 8279cc44e8..d90f34248a 100644 --- a/src/rendering/filters/gaussblur/GaussBlurFilter.h +++ b/src/rendering/filters/gaussblur/GaussBlurFilter.h @@ -24,28 +24,28 @@ namespace pag { class GaussBlurFilter : public LayerFilter { - public: - explicit GaussBlurFilter(Effect* effect); - ~GaussBlurFilter() override; +public: + explicit GaussBlurFilter(Effect* effect); + ~GaussBlurFilter() override; - bool initialize(Context* context) override; + bool initialize(Context* context) override; - void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; + void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; - void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - SinglePassBlurFilter* blurFilterH = nullptr; - SinglePassBlurFilter* blurFilterV = nullptr; + SinglePassBlurFilter* blurFilterH = nullptr; + SinglePassBlurFilter* blurFilterV = nullptr; - std::shared_ptr blurFilterBuffer = nullptr; + std::shared_ptr blurFilterBuffer = nullptr; - bool repeatEdge = true; - BlurDirection blurDirection = BlurDirection::Both; - float blurriness = 0.0f; - std::vector filtersBounds = {}; + bool repeatEdge = true; + BlurDirection blurDirection = BlurDirection::Both; + float blurriness = 0.0f; + std::vector filtersBounds = {}; }; } // namespace pag diff --git a/src/rendering/filters/gaussblur/SinglePassBlurFilter.cpp b/src/rendering/filters/gaussblur/SinglePassBlurFilter.cpp index 45ed368812..753fdb7f83 100644 --- a/src/rendering/filters/gaussblur/SinglePassBlurFilter.cpp +++ b/src/rendering/filters/gaussblur/SinglePassBlurFilter.cpp @@ -81,90 +81,92 @@ SinglePassBlurFilter::SinglePassBlurFilter(BlurDirection direction) : direction( } std::string SinglePassBlurFilter::onBuildFragmentShader() { - return BLUR_FRAGMENT_SHADER; + return BLUR_FRAGMENT_SHADER; } void SinglePassBlurFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - radiusHandle = gl->getUniformLocation(program, "uRadius"); - levelHandle = gl->getUniformLocation(program, "uLevel"); - repeatEdgeHandle = gl->getUniformLocation(program, "uRepeatEdge"); - colorHandle = gl->getUniformLocation(program, "uColor"); - colorValidHandle = gl->getUniformLocation(program, "uColorValid"); - opacityHandle = gl->getUniformLocation(program, "uOpacity"); + radiusHandle = gl->getUniformLocation(program, "uRadius"); + levelHandle = gl->getUniformLocation(program, "uLevel"); + repeatEdgeHandle = gl->getUniformLocation(program, "uRepeatEdge"); + colorHandle = gl->getUniformLocation(program, "uColor"); + colorValidHandle = gl->getUniformLocation(program, "uColorValid"); + opacityHandle = gl->getUniformLocation(program, "uOpacity"); } void SinglePassBlurFilter::updateParams(float blurrinessValue, float blurOpacityValue, bool repeatEdgeValue, BlurMode mode) { - blurriness = blurrinessValue; - opacity = blurOpacityValue; - repeatEdge = repeatEdgeValue; - switch (mode) { + blurriness = blurrinessValue; + opacity = blurOpacityValue; + repeatEdge = repeatEdgeValue; + switch (mode) { case BlurMode::Picture: - this->maxRadius = BLUR_MODE_PIC_MAX_RADIUS; - this->maxLevel = BLUR_MODE_PIC_MAX_LEVEL; - break; + this->maxRadius = BLUR_MODE_PIC_MAX_RADIUS; + this->maxLevel = BLUR_MODE_PIC_MAX_LEVEL; + break; case BlurMode::Shadow: - this->maxRadius = BLUR_MODE_SHADOW_MAX_RADIUS; - this->maxLevel = BLUR_MODE_SHADOW_MAX_LEVEL; - break; + this->maxRadius = BLUR_MODE_SHADOW_MAX_RADIUS; + this->maxLevel = BLUR_MODE_SHADOW_MAX_LEVEL; + break; default: - break; - } + break; + } } void SinglePassBlurFilter::enableBlurColor(Color blurColor) { - isColorValid = true; - color = blurColor; + isColorValid = true; + color = blurColor; } void SinglePassBlurFilter::disableBlurColor() { - isColorValid = false; - color = Black; + isColorValid = false; + color = Black; } void SinglePassBlurFilter::onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) { - auto scale = direction == BlurDirection::Horizontal ? filterScale.x : filterScale.y; - - auto blurValue = std::min(blurriness * scale, BLUR_LIMIT_BLURRINESS); - auto blurRadius = blurValue / BLUR_LIMIT_BLURRINESS * (maxRadius - 1.0) + 1.0; - auto blurLevel = blurValue / BLUR_LIMIT_BLURRINESS * (maxLevel - 1.0) + 1.0; - - gl->uniform1f(radiusHandle, blurRadius); - gl->uniform2f(levelHandle, - blurLevel / static_cast(contentBounds.width()) * - (direction == BlurDirection::Horizontal), - blurLevel / static_cast(contentBounds.height()) * - (direction == BlurDirection::Vertical)); - gl->uniform1f(repeatEdgeHandle, repeatEdge); - gl->uniform3f(colorHandle, color.red / 255.f, color.green / 255.f, color.blue / 255.f); - gl->uniform1f(colorValidHandle, isColorValid); - gl->uniform1f(opacityHandle, opacity); + const Point& filterScale) { + auto scale = direction == BlurDirection::Horizontal ? filterScale.x : filterScale.y; + + auto blurValue = std::min(blurriness * scale, BLUR_LIMIT_BLURRINESS); + auto blurRadius = blurValue / BLUR_LIMIT_BLURRINESS * (maxRadius - 1.0) + 1.0; + auto blurLevel = blurValue / BLUR_LIMIT_BLURRINESS * (maxLevel - 1.0) + 1.0; + + gl->uniform1f(radiusHandle, blurRadius); + gl->uniform2f(levelHandle, + blurLevel / static_cast(contentBounds.width()) * + (direction == BlurDirection::Horizontal), + blurLevel / static_cast(contentBounds.height()) * + (direction == BlurDirection::Vertical)); + gl->uniform1f(repeatEdgeHandle, repeatEdge); + gl->uniform3f(colorHandle, color.red / 255.f, color.green / 255.f, color.blue / 255.f); + gl->uniform1f(colorValidHandle, isColorValid); + gl->uniform1f(opacityHandle, opacity); } std::vector SinglePassBlurFilter::computeVertices(const Rect& inputBounds, - const Rect& outputBounds, - const Point& filterScale) { - if (repeatEdge) { - return LayerFilter::computeVertices(inputBounds, outputBounds, filterScale); - } - std::vector vertices = {}; - Point contentPoint[4] = {{outputBounds.left, outputBounds.bottom}, - {outputBounds.right, outputBounds.bottom}, - {outputBounds.left, outputBounds.top}, - {outputBounds.right, outputBounds.top}}; - - auto deltaX = direction == BlurDirection::Horizontal ? -blurriness * filterScale.x : 0; - auto deltaY = direction == BlurDirection::Vertical ? -blurriness * filterScale.y : 0; - - Point texturePoints[4] = {{deltaX, (outputBounds.height() + deltaY)}, - {(outputBounds.width() + deltaX), (outputBounds.height() + deltaY)}, - {deltaX, deltaY}, - {(outputBounds.width() + deltaX), deltaY}}; - for (int ii = 0; ii < 4; ii++) { - vertices.push_back(contentPoint[ii]); - vertices.push_back(texturePoints[ii]); - } - return vertices; + const Rect& outputBounds, + const Point& filterScale) { + if (repeatEdge) { + return LayerFilter::computeVertices(inputBounds, outputBounds, filterScale); + } + std::vector vertices = {}; + Point contentPoint[4] = {{outputBounds.left, outputBounds.bottom}, + {outputBounds.right, outputBounds.bottom}, + {outputBounds.left, outputBounds.top}, + {outputBounds.right, outputBounds.top} + }; + + auto deltaX = direction == BlurDirection::Horizontal ? -blurriness * filterScale.x : 0; + auto deltaY = direction == BlurDirection::Vertical ? -blurriness * filterScale.y : 0; + + Point texturePoints[4] = {{deltaX, (outputBounds.height() + deltaY)}, + {(outputBounds.width() + deltaX), (outputBounds.height() + deltaY)}, + {deltaX, deltaY}, + {(outputBounds.width() + deltaX), deltaY} + }; + for (int ii = 0; ii < 4; ii++) { + vertices.push_back(contentPoint[ii]); + vertices.push_back(texturePoints[ii]); + } + return vertices; } } // namespace pag diff --git a/src/rendering/filters/gaussblur/SinglePassBlurFilter.h b/src/rendering/filters/gaussblur/SinglePassBlurFilter.h index 1bbdfb83d1..4b942b578f 100644 --- a/src/rendering/filters/gaussblur/SinglePassBlurFilter.h +++ b/src/rendering/filters/gaussblur/SinglePassBlurFilter.h @@ -23,41 +23,41 @@ namespace pag { class SinglePassBlurFilter : public LayerFilter { - public: - explicit SinglePassBlurFilter(BlurDirection blurDirection); - ~SinglePassBlurFilter() override = default; - - void updateParams(float blurriness, float opacity, bool repeatEdge, BlurMode mode); - - void enableBlurColor(Color blurColor); - void disableBlurColor(); - - protected: - std::string onBuildFragmentShader() override; - - void onPrepareProgram(const GLInterface* gl, unsigned program) override; - - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; - - std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; - - private: - int radiusHandle = -1; - int levelHandle = -1; - int repeatEdgeHandle = -1; - int colorHandle = -1; - int colorValidHandle = -1; - int opacityHandle = -1; - - BlurDirection direction; - Color color = Black; - bool isColorValid = false; - float blurriness = 0.0; - float opacity = 1.0f; - bool repeatEdge = true; - float maxRadius = 3.0f; - float maxLevel = 13.0f; +public: + explicit SinglePassBlurFilter(BlurDirection blurDirection); + ~SinglePassBlurFilter() override = default; + + void updateParams(float blurriness, float opacity, bool repeatEdge, BlurMode mode); + + void enableBlurColor(Color blurColor); + void disableBlurColor(); + +protected: + std::string onBuildFragmentShader() override; + + void onPrepareProgram(const GLInterface* gl, unsigned program) override; + + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; + + std::vector computeVertices(const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; + +private: + int radiusHandle = -1; + int levelHandle = -1; + int repeatEdgeHandle = -1; + int colorHandle = -1; + int colorValidHandle = -1; + int opacityHandle = -1; + + BlurDirection direction; + Color color = Black; + bool isColorValid = false; + float blurriness = 0.0; + float opacity = 1.0f; + bool repeatEdge = true; + float maxRadius = 3.0f; + float maxLevel = 13.0f; }; } // namespace pag diff --git a/src/rendering/filters/glow/GlowBlurFilter.cpp b/src/rendering/filters/glow/GlowBlurFilter.cpp index 526acb9894..69c981ce19 100644 --- a/src/rendering/filters/glow/GlowBlurFilter.cpp +++ b/src/rendering/filters/glow/GlowBlurFilter.cpp @@ -65,26 +65,26 @@ GlowBlurFilter::GlowBlurFilter(BlurDirection direction) : blurDirection(directio } std::string GlowBlurFilter::onBuildVertexShader() { - return GLOW_BLUR_VERTEX_SHADER; + return GLOW_BLUR_VERTEX_SHADER; } std::string GlowBlurFilter::onBuildFragmentShader() { - return GLOW_BLUR_FRAGMENT_SHADER; + return GLOW_BLUR_FRAGMENT_SHADER; } void GlowBlurFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - textureOffsetHHandle = gl->getUniformLocation(program, "textureOffsetH"); - textureOffsetVHandle = gl->getUniformLocation(program, "textureOffsetV"); + textureOffsetHHandle = gl->getUniformLocation(program, "textureOffsetH"); + textureOffsetVHandle = gl->getUniformLocation(program, "textureOffsetV"); } void GlowBlurFilter::updateOffset(float offset) { - blurOffset = offset; + blurOffset = offset; } void GlowBlurFilter::onUpdateParams(const GLInterface* gl, const Rect&, const Point&) { - auto textureOffsetH = blurDirection == BlurDirection::Horizontal ? blurOffset : 0; - auto textureOffsetV = blurDirection == BlurDirection::Vertical ? blurOffset : 0; - gl->uniform1f(textureOffsetHHandle, textureOffsetH); - gl->uniform1f(textureOffsetVHandle, textureOffsetV); + auto textureOffsetH = blurDirection == BlurDirection::Horizontal ? blurOffset : 0; + auto textureOffsetV = blurDirection == BlurDirection::Vertical ? blurOffset : 0; + gl->uniform1f(textureOffsetHHandle, textureOffsetH); + gl->uniform1f(textureOffsetVHandle, textureOffsetV); } } // namespace pag diff --git a/src/rendering/filters/glow/GlowBlurFilter.h b/src/rendering/filters/glow/GlowBlurFilter.h index 9356d05b18..e9050fcd99 100644 --- a/src/rendering/filters/glow/GlowBlurFilter.h +++ b/src/rendering/filters/glow/GlowBlurFilter.h @@ -23,26 +23,26 @@ namespace pag { class GlowBlurFilter : public LayerFilter { - public: - explicit GlowBlurFilter(BlurDirection blurDirection); - ~GlowBlurFilter() override = default; +public: + explicit GlowBlurFilter(BlurDirection blurDirection); + ~GlowBlurFilter() override = default; - void updateOffset(float blurOffset); + void updateOffset(float blurOffset); - protected: - std::string onBuildVertexShader() override; +protected: + std::string onBuildVertexShader() override; - std::string onBuildFragmentShader() override; + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - int textureOffsetHHandle = -1; - int textureOffsetVHandle = -1; - BlurDirection blurDirection; - float blurOffset = 0.0f; +private: + int textureOffsetHHandle = -1; + int textureOffsetVHandle = -1; + BlurDirection blurDirection; + float blurOffset = 0.0f; }; } // namespace pag diff --git a/src/rendering/filters/glow/GlowFilter.cpp b/src/rendering/filters/glow/GlowFilter.cpp index 564f9cb7f3..fc21dfba77 100644 --- a/src/rendering/filters/glow/GlowFilter.cpp +++ b/src/rendering/filters/glow/GlowFilter.cpp @@ -22,90 +22,90 @@ namespace pag { GlowFilter::GlowFilter(Effect* effect) : effect(effect) { - blurFilterH = new GlowBlurFilter(BlurDirection::Horizontal); - blurFilterV = new GlowBlurFilter(BlurDirection::Vertical); - targetFilter = new GlowMergeFilter(effect); + blurFilterH = new GlowBlurFilter(BlurDirection::Horizontal); + blurFilterV = new GlowBlurFilter(BlurDirection::Vertical); + targetFilter = new GlowMergeFilter(effect); } GlowFilter::~GlowFilter() { - delete blurFilterH; - delete blurFilterV; - delete targetFilter; + delete blurFilterH; + delete blurFilterV; + delete targetFilter; } bool GlowFilter::initialize(Context* context) { - if (!blurFilterH->initialize(context)) { - return false; - } - if (!blurFilterV->initialize(context)) { - return false; - } - if (!targetFilter->initialize(context)) { - return false; - } - return true; + if (!blurFilterH->initialize(context)) { + return false; + } + if (!blurFilterV->initialize(context)) { + return false; + } + if (!targetFilter->initialize(context)) { + return false; + } + return true; } void GlowFilter::update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, const Point& filterScale) { - LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); + LayerFilter::update(frame, contentBounds, transformedBounds, filterScale); - auto glowEffect = static_cast(effect); - auto glowRadius = glowEffect->glowRadius->getValueAt(layerFrame); - resizeRatio = 1.0f - glowRadius / 1500.f; - auto blurBounds = contentBounds; - blurBounds.scale(resizeRatio, resizeRatio); - blurBounds.offsetTo(contentBounds.left, contentBounds.top); - blurBounds.roundOut(); - blurFilterV->update(frame, contentBounds, blurBounds, filterScale); - blurFilterH->update(frame, contentBounds, blurBounds, filterScale); - targetFilter->update(frame, contentBounds, transformedBounds, filterScale); + auto glowEffect = static_cast(effect); + auto glowRadius = glowEffect->glowRadius->getValueAt(layerFrame); + resizeRatio = 1.0f - glowRadius / 1500.f; + auto blurBounds = contentBounds; + blurBounds.scale(resizeRatio, resizeRatio); + blurBounds.offsetTo(contentBounds.left, contentBounds.top); + blurBounds.roundOut(); + blurFilterV->update(frame, contentBounds, blurBounds, filterScale); + blurFilterH->update(frame, contentBounds, blurBounds, filterScale); + targetFilter->update(frame, contentBounds, transformedBounds, filterScale); } bool GlowFilter::checkBuffer(Context* context, int blurWidth, int blurHeight) { - if (blurFilterBufferH == nullptr || blurFilterBufferH->width() != blurWidth || - blurFilterBufferH->height() != blurHeight) { - blurFilterBufferH = FilterBuffer::Make(context, blurWidth, blurHeight); - } - if (blurFilterBufferH == nullptr) { - return false; - } - if (blurFilterBufferV == nullptr || blurFilterBufferV->width() != blurWidth || - blurFilterBufferV->height() != blurHeight) { - blurFilterBufferV = FilterBuffer::Make(context, blurWidth, blurHeight); - } - if (blurFilterBufferV == nullptr) { - blurFilterBufferH = nullptr; - return false; - } - return true; + if (blurFilterBufferH == nullptr || blurFilterBufferH->width() != blurWidth || + blurFilterBufferH->height() != blurHeight) { + blurFilterBufferH = FilterBuffer::Make(context, blurWidth, blurHeight); + } + if (blurFilterBufferH == nullptr) { + return false; + } + if (blurFilterBufferV == nullptr || blurFilterBufferV->width() != blurWidth || + blurFilterBufferV->height() != blurHeight) { + blurFilterBufferV = FilterBuffer::Make(context, blurWidth, blurHeight); + } + if (blurFilterBufferV == nullptr) { + blurFilterBufferH = nullptr; + return false; + } + return true; } void GlowFilter::draw(Context* context, const FilterSource* source, const FilterTarget* target) { - if (source == nullptr || target == nullptr) { - LOGE("GlowFilter::draw() can not draw filter"); - return; - } - auto blurWidth = static_cast(ceilf(source->width * resizeRatio)); - auto blurHeight = static_cast(ceilf(source->height * resizeRatio)); + if (source == nullptr || target == nullptr) { + LOGE("GlowFilter::draw() can not draw filter"); + return; + } + auto blurWidth = static_cast(ceilf(source->width * resizeRatio)); + auto blurHeight = static_cast(ceilf(source->height * resizeRatio)); - if (!checkBuffer(context, blurWidth, blurHeight)) { - return; - } - auto gl = GLContext::Unwrap(context); - blurFilterBufferH->clearColor(gl); - blurFilterBufferV->clearColor(gl); + if (!checkBuffer(context, blurWidth, blurHeight)) { + return; + } + auto gl = GLContext::Unwrap(context); + blurFilterBufferH->clearColor(gl); + blurFilterBufferV->clearColor(gl); - auto targetH = blurFilterBufferH->toFilterTarget(Matrix::I()); - blurFilterH->updateOffset(1.0f / blurWidth); - blurFilterH->draw(context, source, targetH.get()); + auto targetH = blurFilterBufferH->toFilterTarget(Matrix::I()); + blurFilterH->updateOffset(1.0f / blurWidth); + blurFilterH->draw(context, source, targetH.get()); - auto sourceV = blurFilterBufferH->toFilterSource(source->scale); - auto targetV = blurFilterBufferV->toFilterTarget(Matrix::I()); - blurFilterV->updateOffset(1.0f / blurHeight); - blurFilterV->draw(context, sourceV.get(), targetV.get()); + auto sourceV = blurFilterBufferH->toFilterSource(source->scale); + auto targetV = blurFilterBufferV->toFilterTarget(Matrix::I()); + blurFilterV->updateOffset(1.0f / blurHeight); + blurFilterV->draw(context, sourceV.get(), targetV.get()); - targetFilter->updateTexture(blurFilterBufferV->getTexture().id); - targetFilter->draw(context, source, target); + targetFilter->updateTexture(blurFilterBufferV->getTexture().id); + targetFilter->draw(context, source, target); } } // namespace pag diff --git a/src/rendering/filters/glow/GlowFilter.h b/src/rendering/filters/glow/GlowFilter.h index 8034775e60..674cafd7e5 100644 --- a/src/rendering/filters/glow/GlowFilter.h +++ b/src/rendering/filters/glow/GlowFilter.h @@ -25,29 +25,29 @@ namespace pag { class GlowFilter : public LayerFilter { - public: - explicit GlowFilter(Effect* effect); - ~GlowFilter() override; +public: + explicit GlowFilter(Effect* effect); + ~GlowFilter() override; - bool initialize(Context* context) override; + bool initialize(Context* context) override; - void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; + void draw(Context* context, const FilterSource* source, const FilterTarget* target) override; - void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, - const Point& filterScale) override; + void update(Frame frame, const Rect& contentBounds, const Rect& transformedBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - float resizeRatio = 1.0f; + float resizeRatio = 1.0f; - GlowBlurFilter* blurFilterH = nullptr; - GlowBlurFilter* blurFilterV = nullptr; - GlowMergeFilter* targetFilter = nullptr; + GlowBlurFilter* blurFilterH = nullptr; + GlowBlurFilter* blurFilterV = nullptr; + GlowMergeFilter* targetFilter = nullptr; - std::shared_ptr blurFilterBufferH = nullptr; - std::shared_ptr blurFilterBufferV = nullptr; + std::shared_ptr blurFilterBufferH = nullptr; + std::shared_ptr blurFilterBufferV = nullptr; - bool checkBuffer(Context* context, int blurWidth, int blurHeight); + bool checkBuffer(Context* context, int blurWidth, int blurHeight); }; } // namespace pag diff --git a/src/rendering/filters/glow/GlowMergeFilter.cpp b/src/rendering/filters/glow/GlowMergeFilter.cpp index 49d6a7f8ce..aa0ab2c89a 100644 --- a/src/rendering/filters/glow/GlowMergeFilter.cpp +++ b/src/rendering/filters/glow/GlowMergeFilter.cpp @@ -47,27 +47,27 @@ GlowMergeFilter::GlowMergeFilter(Effect* effect) : effect(effect) { } std::string GlowMergeFilter::onBuildFragmentShader() { - return GLOW_TARGET_FRAGMENT_SHADER; + return GLOW_TARGET_FRAGMENT_SHADER; } void GlowMergeFilter::onPrepareProgram(const GLInterface* gl, unsigned int program) { - inputTextureHandle = gl->getUniformLocation(program, "inputImageTexture"); - blurTextureHandle = gl->getUniformLocation(program, "blurImageTexture"); - progressHandle = gl->getUniformLocation(program, "progress"); + inputTextureHandle = gl->getUniformLocation(program, "inputImageTexture"); + blurTextureHandle = gl->getUniformLocation(program, "blurImageTexture"); + progressHandle = gl->getUniformLocation(program, "progress"); } void GlowMergeFilter::updateTexture(unsigned blurTexture) { - blurTextureID = blurTexture; + blurTextureID = blurTexture; } void GlowMergeFilter::onUpdateParams(const GLInterface* gl, const Rect&, const Point&) { - auto glowEffect = static_cast(effect); - auto glowThreshold = glowEffect->glowThreshold->getValueAt(layerFrame); - gl->uniform1f(progressHandle, glowThreshold); - gl->uniform1i(inputTextureHandle, 0); - // TODO(domrjchen): 下面这行之前写成了 gl->uniform1i(progressHandle, 1), 会导致 glError, - // 暂时注释掉。目前的发光效果跟 AE 也没有对齐,后面重写发光效果时时再修复。 - // gl->uniform1i(blurTextureHandle, 1); - ActiveTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, blurTextureID); + auto glowEffect = static_cast(effect); + auto glowThreshold = glowEffect->glowThreshold->getValueAt(layerFrame); + gl->uniform1f(progressHandle, glowThreshold); + gl->uniform1i(inputTextureHandle, 0); + // TODO(domrjchen): 下面这行之前写成了 gl->uniform1i(progressHandle, 1), 会导致 glError, + // 暂时注释掉。目前的发光效果跟 AE 也没有对齐,后面重写发光效果时时再修复。 + // gl->uniform1i(blurTextureHandle, 1); + ActiveTexture(gl, GL::TEXTURE1, GL::TEXTURE_2D, blurTextureID); } } // namespace pag diff --git a/src/rendering/filters/glow/GlowMergeFilter.h b/src/rendering/filters/glow/GlowMergeFilter.h index 3104b8df4e..4ffa49ef70 100644 --- a/src/rendering/filters/glow/GlowMergeFilter.h +++ b/src/rendering/filters/glow/GlowMergeFilter.h @@ -22,26 +22,26 @@ namespace pag { class GlowMergeFilter : public LayerFilter { - public: - explicit GlowMergeFilter(Effect* effect); - ~GlowMergeFilter() override = default; +public: + explicit GlowMergeFilter(Effect* effect); + ~GlowMergeFilter() override = default; - void updateTexture(unsigned blurTexture); + void updateTexture(unsigned blurTexture); - protected: - std::string onBuildFragmentShader() override; +protected: + std::string onBuildFragmentShader() override; - void onPrepareProgram(const GLInterface* gl, unsigned program) override; + void onPrepareProgram(const GLInterface* gl, unsigned program) override; - void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, - const Point& filterScale) override; + void onUpdateParams(const GLInterface* gl, const Rect& contentBounds, + const Point& filterScale) override; - private: - Effect* effect = nullptr; +private: + Effect* effect = nullptr; - int inputTextureHandle = -1; - int blurTextureHandle = -1; - int progressHandle = -1; - unsigned blurTextureID = 0; + int inputTextureHandle = -1; + int blurTextureHandle = -1; + int progressHandle = -1; + unsigned blurTextureID = 0; }; } // namespace pag diff --git a/src/rendering/filters/utils/BlurTypes.h b/src/rendering/filters/utils/BlurTypes.h index d1739ce50c..1909a9dd72 100644 --- a/src/rendering/filters/utils/BlurTypes.h +++ b/src/rendering/filters/utils/BlurTypes.h @@ -29,12 +29,12 @@ namespace pag { #define DROPSHADOW_SPREAD_MIN_THICK_SIZE (12.0f) enum class BlurMode { - Picture = 0, - Shadow = 1, + Picture = 0, + Shadow = 1, }; enum class BlurDirection { - Both = 0, - Vertical = 1, - Horizontal = 2, + Both = 0, + Vertical = 1, + Horizontal = 2, }; } // namespace pag diff --git a/src/rendering/filters/utils/FilterBuffer.cpp b/src/rendering/filters/utils/FilterBuffer.cpp index b2aa2c8fd5..2cfebd8b5c 100644 --- a/src/rendering/filters/utils/FilterBuffer.cpp +++ b/src/rendering/filters/utils/FilterBuffer.cpp @@ -21,47 +21,47 @@ namespace pag { std::shared_ptr FilterBuffer::Make(Context* context, int width, int height, - bool usesMSAA) { - auto texture = GLTexture::MakeRGBA(context, width, height); - auto gl = GLContext::Unwrap(context); - auto sampleCount = usesMSAA ? gl->caps->getSampleCount(4, PixelConfig::RGBA_8888) : 1; - auto renderTarget = GLRenderTarget::MakeFrom(context, texture.get(), sampleCount); - if (renderTarget == nullptr) { - return nullptr; - } - auto buffer = new FilterBuffer(); - buffer->texture = texture; - buffer->renderTarget = renderTarget; - return std::shared_ptr(buffer); + bool usesMSAA) { + auto texture = GLTexture::MakeRGBA(context, width, height); + auto gl = GLContext::Unwrap(context); + auto sampleCount = usesMSAA ? gl->caps->getSampleCount(4, PixelConfig::RGBA_8888) : 1; + auto renderTarget = GLRenderTarget::MakeFrom(context, texture.get(), sampleCount); + if (renderTarget == nullptr) { + return nullptr; + } + auto buffer = new FilterBuffer(); + buffer->texture = texture; + buffer->renderTarget = renderTarget; + return std::shared_ptr(buffer); } void FilterBuffer::resolve(Context* context) { - renderTarget->resolve(context); + renderTarget->resolve(context); } void FilterBuffer::clearColor(const GLInterface* gl) const { - renderTarget->clear(gl); + renderTarget->clear(gl); } std::unique_ptr FilterBuffer::toFilterSource(const Point& scale) const { - auto filterSource = new FilterSource(); - filterSource->textureID = getTexture().id; - filterSource->width = texture->width(); - filterSource->height = texture->height(); - filterSource->scale = scale; - // TODO(domrjchen): 这里的 ImageOrigin 是错的 - filterSource->textureMatrix = - ToGLTextureMatrix(Matrix::I(), texture->width(), texture->height(), ImageOrigin::BottomLeft); - return std::unique_ptr(filterSource); + auto filterSource = new FilterSource(); + filterSource->textureID = getTexture().id; + filterSource->width = texture->width(); + filterSource->height = texture->height(); + filterSource->scale = scale; + // TODO(domrjchen): 这里的 ImageOrigin 是错的 + filterSource->textureMatrix = + ToGLTextureMatrix(Matrix::I(), texture->width(), texture->height(), ImageOrigin::BottomLeft); + return std::unique_ptr(filterSource); } std::unique_ptr FilterBuffer::toFilterTarget(const Matrix& drawingMatrix) const { - auto filterTarget = new FilterTarget(); - filterTarget->frameBufferID = getFramebuffer().id; - filterTarget->width = renderTarget->width(); - filterTarget->height = renderTarget->height(); - filterTarget->vertexMatrix = ToGLVertexMatrix(drawingMatrix, renderTarget->width(), - renderTarget->height(), ImageOrigin::BottomLeft); - return std::unique_ptr(filterTarget); + auto filterTarget = new FilterTarget(); + filterTarget->frameBufferID = getFramebuffer().id; + filterTarget->width = renderTarget->width(); + filterTarget->height = renderTarget->height(); + filterTarget->vertexMatrix = ToGLVertexMatrix(drawingMatrix, renderTarget->width(), + renderTarget->height(), ImageOrigin::BottomLeft); + return std::unique_ptr(filterTarget); } } // namespace pag diff --git a/src/rendering/filters/utils/FilterBuffer.h b/src/rendering/filters/utils/FilterBuffer.h index a065ed5104..f036e5741d 100644 --- a/src/rendering/filters/utils/FilterBuffer.h +++ b/src/rendering/filters/utils/FilterBuffer.h @@ -25,41 +25,41 @@ namespace pag { class FilterBuffer { - public: - static std::shared_ptr Make(Context* context, int width, int height, - bool usesMSAA = false); +public: + static std::shared_ptr Make(Context* context, int width, int height, + bool usesMSAA = false); - void clearColor(const GLInterface* gl) const; + void clearColor(const GLInterface* gl) const; - std::unique_ptr toFilterSource(const Point& scale) const; + std::unique_ptr toFilterSource(const Point& scale) const; - std::unique_ptr toFilterTarget(const Matrix& drawingMatrix) const; + std::unique_ptr toFilterTarget(const Matrix& drawingMatrix) const; - int width() const { - return renderTarget->width(); - } + int width() const { + return renderTarget->width(); + } - int height() const { - return renderTarget->height(); - } + int height() const { + return renderTarget->height(); + } - bool usesMSAA() const { - return renderTarget->usesMSAA(); - } + bool usesMSAA() const { + return renderTarget->usesMSAA(); + } - GLFrameBufferInfo getFramebuffer() const { - return renderTarget->getGLInfo(); - } + GLFrameBufferInfo getFramebuffer() const { + return renderTarget->getGLInfo(); + } - GLTextureInfo getTexture() const { - return texture->getGLInfo(); - } + GLTextureInfo getTexture() const { + return texture->getGLInfo(); + } - void resolve(Context* context); + void resolve(Context* context); - private: - std::shared_ptr renderTarget = nullptr; - std::shared_ptr texture = nullptr; - FilterBuffer() = default; +private: + std::shared_ptr renderTarget = nullptr; + std::shared_ptr texture = nullptr; + FilterBuffer() = default; }; } // namespace pag diff --git a/src/rendering/filters/utils/FilterHelper.cpp b/src/rendering/filters/utils/FilterHelper.cpp index b9dff6637b..b31b31a96f 100644 --- a/src/rendering/filters/utils/FilterHelper.cpp +++ b/src/rendering/filters/utils/FilterHelper.cpp @@ -23,74 +23,75 @@ namespace pag { Matrix ToMatrix(const FilterTarget* target, bool flipY) { - Matrix matrix = {}; - auto values = target->vertexMatrix; - matrix.setAll(values[0], values[3], values[6], values[1], values[4], values[7], values[2], - values[5], values[8]); - if (flipY) { - matrix.postScale(1.0f, -1.0f); - } - Matrix convertMatrix = {}; - // 以下等价于: - // convertMatrix.setScale(2f/width, 2f/height); - // convertMatrix.postTranslate(-1.0f, -1.0f); - // convertMatrix.postScale(1.0f, -1.0f); - convertMatrix.setAll(2.0f / static_cast(target->width), 0.0f, -1.0f, 0.0f, - -2.0f / static_cast(target->height), 1.0f, 0.0f, 0.0f, 1.0f); - matrix.preConcat(convertMatrix); - if (convertMatrix.invert(&convertMatrix)) { - matrix.postConcat(convertMatrix); - } - return matrix; + Matrix matrix = {}; + auto values = target->vertexMatrix; + matrix.setAll(values[0], values[3], values[6], values[1], values[4], values[7], values[2], + values[5], values[8]); + if (flipY) { + matrix.postScale(1.0f, -1.0f); + } + Matrix convertMatrix = {}; + // 以下等价于: + // convertMatrix.setScale(2f/width, 2f/height); + // convertMatrix.postTranslate(-1.0f, -1.0f); + // convertMatrix.postScale(1.0f, -1.0f); + convertMatrix.setAll(2.0f / static_cast(target->width), 0.0f, -1.0f, 0.0f, + -2.0f / static_cast(target->height), 1.0f, 0.0f, 0.0f, 1.0f); + matrix.preConcat(convertMatrix); + if (convertMatrix.invert(&convertMatrix)) { + matrix.postConcat(convertMatrix); + } + return matrix; } std::unique_ptr ToFilterSource(const Texture* texture, const Point& scale) { - if (texture == nullptr) { - return nullptr; - } - auto textureInfo = GLTexture::Unwrap(texture); - auto filterSource = new FilterSource(); - filterSource->textureID = textureInfo.id; - filterSource->width = texture->width(); - filterSource->height = texture->height(); - filterSource->scale = scale; - filterSource->textureMatrix = - ToGLTextureMatrix(Matrix::I(), texture->width(), texture->height(), texture->origin()); - return std::unique_ptr(filterSource); + if (texture == nullptr) { + return nullptr; + } + auto textureInfo = GLTexture::Unwrap(texture); + auto filterSource = new FilterSource(); + filterSource->textureID = textureInfo.id; + filterSource->width = texture->width(); + filterSource->height = texture->height(); + filterSource->scale = scale; + filterSource->textureMatrix = + ToGLTextureMatrix(Matrix::I(), texture->width(), texture->height(), texture->origin()); + return std::unique_ptr(filterSource); } std::unique_ptr ToFilterTarget(const Surface* surface, const Matrix& drawingMatrix) { - if (surface == nullptr) { - return nullptr; - } - auto renderTarget = static_cast(surface)->getRenderTarget(); - auto filterTarget = new FilterTarget(); - filterTarget->frameBufferID = renderTarget->getGLInfo().id; - filterTarget->width = surface->width(); - filterTarget->height = surface->height(); - filterTarget->vertexMatrix = - ToGLVertexMatrix(drawingMatrix, surface->width(), surface->height(), surface->origin()); - return std::unique_ptr(filterTarget); + if (surface == nullptr) { + return nullptr; + } + auto renderTarget = static_cast(surface)->getRenderTarget(); + auto filterTarget = new FilterTarget(); + filterTarget->frameBufferID = renderTarget->getGLInfo().id; + filterTarget->width = surface->width(); + filterTarget->height = surface->height(); + filterTarget->vertexMatrix = + ToGLVertexMatrix(drawingMatrix, surface->width(), surface->height(), surface->origin()); + return std::unique_ptr(filterTarget); } Point ToGLTexturePoint(const FilterSource* source, const Point& texturePoint) { - return {texturePoint.x * source->scale.x / static_cast(source->width), - (static_cast(source->height) - texturePoint.y * source->scale.y) / - static_cast(source->height)}; + return {texturePoint.x * source->scale.x / static_cast(source->width), + (static_cast(source->height) - texturePoint.y * source->scale.y) / + static_cast(source->height)}; } Point ToGLVertexPoint(const FilterTarget* target, const FilterSource* source, const Rect& contentBounds, const Point& contentPoint) { - Point vertexPoint = {(contentPoint.x - contentBounds.left) * source->scale.x, - (contentPoint.y - contentBounds.top) * source->scale.y}; - return {2.0f * vertexPoint.x / static_cast(target->width) - 1.0f, - 1.0f - 2.0f * vertexPoint.y / static_cast(target->height)}; + Point vertexPoint = {(contentPoint.x - contentBounds.left) * source->scale.x, + (contentPoint.y - contentBounds.top) * source->scale.y + }; + return {2.0f * vertexPoint.x / static_cast(target->width) - 1.0f, + 1.0f - 2.0f * vertexPoint.y / static_cast(target->height)}; } void PreConcatMatrix(FilterTarget* target, const Matrix& matrix) { - auto vertexMatrix = ToMatrix(target); - vertexMatrix.preConcat(matrix); - target->vertexMatrix = - ToGLVertexMatrix(vertexMatrix, target->width, target->height, ImageOrigin::BottomLeft); + auto vertexMatrix = ToMatrix(target); + vertexMatrix.preConcat(matrix); + target->vertexMatrix = + ToGLVertexMatrix(vertexMatrix, target->width, target->height, ImageOrigin::BottomLeft); } } // namespace pag diff --git a/src/rendering/graphics/FontManager.cpp b/src/rendering/graphics/FontManager.cpp index df3c1883e4..df46279589 100644 --- a/src/rendering/graphics/FontManager.cpp +++ b/src/rendering/graphics/FontManager.cpp @@ -22,203 +22,203 @@ namespace pag { std::shared_ptr TypefaceHolder::MakeFromName(const std::string& fontFamily, - const std::string& fontStyle) { - auto holder = new TypefaceHolder(); - holder->fontFamily = fontFamily; - holder->fontStyle = fontStyle; - return std::shared_ptr(holder); + const std::string& fontStyle) { + auto holder = new TypefaceHolder(); + holder->fontFamily = fontFamily; + holder->fontStyle = fontStyle; + return std::shared_ptr(holder); } std::shared_ptr TypefaceHolder::MakeFromFile(const std::string& fontPath, - int ttcIndex) { - auto holder = new TypefaceHolder(); - holder->fontPath = fontPath; - holder->ttcIndex = ttcIndex; - return std::shared_ptr(holder); + int ttcIndex) { + auto holder = new TypefaceHolder(); + holder->fontPath = fontPath; + holder->ttcIndex = ttcIndex; + return std::shared_ptr(holder); } std::shared_ptr TypefaceHolder::getTypeface() { - if (typeface == nullptr) { - if (!fontPath.empty()) { - typeface = Typeface::MakeFromPath(fontPath, ttcIndex); - } else { - typeface = Typeface::MakeFromName(fontFamily, fontStyle); + if (typeface == nullptr) { + if (!fontPath.empty()) { + typeface = Typeface::MakeFromPath(fontPath, ttcIndex); + } else { + typeface = Typeface::MakeFromName(fontFamily, fontStyle); + } } - } - return typeface; + return typeface; } FontManager::~FontManager() { - std::lock_guard autoLock(locker); - registeredFontMap.clear(); + std::lock_guard autoLock(locker); + registeredFontMap.clear(); } PAGFont FontManager::registerFont(const std::string& fontPath, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - std::lock_guard autoLock(locker); - auto font = Platform::Current()->parseFont(fontPath, ttcIndex); - if (font.fontFamily.empty()) { - return font; - } - return registerFont(font, Typeface::MakeFromPath(fontPath, ttcIndex), fontFamily, fontStyle); + std::lock_guard autoLock(locker); + auto font = Platform::Current()->parseFont(fontPath, ttcIndex); + if (font.fontFamily.empty()) { + return font; + } + return registerFont(font, Typeface::MakeFromPath(fontPath, ttcIndex), fontFamily, fontStyle); } PAGFont FontManager::registerFont(const void* data, size_t length, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - std::lock_guard autoLock(locker); - auto font = Platform::Current()->parseFont(data, length, ttcIndex); - if (font.fontFamily.empty()) { - return font; - } - return registerFont(font, Typeface::MakeFromBytes(data, length), fontFamily, fontStyle); + std::lock_guard autoLock(locker); + auto font = Platform::Current()->parseFont(data, length, ttcIndex); + if (font.fontFamily.empty()) { + return font; + } + return registerFont(font, Typeface::MakeFromBytes(data, length), fontFamily, fontStyle); } static std::string PAGFontRegisterKey(const std::string& fontFamily, const std::string& fontStyle) { - return fontFamily + "|" + fontStyle; + return fontFamily + "|" + fontStyle; } PAGFont FontManager::registerFont(const PAGFont& font, std::shared_ptr typeface, const std::string& fontFamily, const std::string& fontStyle) { - if (font.fontFamily.empty() || typeface == nullptr) { - return font; - } - std::string pagFontFamily = font.fontFamily; - std::string pagFontStyle = font.fontStyle; - // 由于各个平台解析出来的 family 和 style 不一样,此处为了统一, - // 如果用户注册时候传入了就使用用户的值 - if (!fontFamily.empty()) { - pagFontFamily = fontFamily; - pagFontStyle = fontStyle; - } - auto key = PAGFontRegisterKey(pagFontFamily, pagFontStyle); - auto iter = registeredFontMap.find(key); - if (iter != registeredFontMap.end()) { - registeredFontMap.erase(iter); - } - registeredFontMap[key] = std::move(typeface); - return {pagFontFamily, pagFontStyle}; + if (font.fontFamily.empty() || typeface == nullptr) { + return font; + } + std::string pagFontFamily = font.fontFamily; + std::string pagFontStyle = font.fontStyle; + // 由于各个平台解析出来的 family 和 style 不一样,此处为了统一, + // 如果用户注册时候传入了就使用用户的值 + if (!fontFamily.empty()) { + pagFontFamily = fontFamily; + pagFontStyle = fontStyle; + } + auto key = PAGFontRegisterKey(pagFontFamily, pagFontStyle); + auto iter = registeredFontMap.find(key); + if (iter != registeredFontMap.end()) { + registeredFontMap.erase(iter); + } + registeredFontMap[key] = std::move(typeface); + return {pagFontFamily, pagFontStyle}; } void FontManager::unregisterFont(const PAGFont& font) { - if (font.fontFamily.empty()) { - return; - } - std::lock_guard autoLock(locker); - auto iter = registeredFontMap.find(PAGFontRegisterKey(font.fontFamily, font.fontStyle)); - if (iter == registeredFontMap.end()) { - return; - } - registeredFontMap.erase(iter); + if (font.fontFamily.empty()) { + return; + } + std::lock_guard autoLock(locker); + auto iter = registeredFontMap.find(PAGFontRegisterKey(font.fontFamily, font.fontStyle)); + if (iter == registeredFontMap.end()) { + return; + } + registeredFontMap.erase(iter); } static std::shared_ptr MakeTypefaceWithName(const std::string& fontFamily, - const std::string& fontStyle) { - auto typeface = Typeface::MakeFromName(fontFamily, fontStyle); - if (typeface != nullptr) { - if (fontFamily != typeface->fontFamily()) { - typeface = nullptr; + const std::string& fontStyle) { + auto typeface = Typeface::MakeFromName(fontFamily, fontStyle); + if (typeface != nullptr) { + if (fontFamily != typeface->fontFamily()) { + typeface = nullptr; + } } - } - return typeface; + return typeface; } std::shared_ptr FontManager::getTypefaceWithoutFallback(const std::string& fontFamily, - const std::string& fontStyle) { - std::shared_ptr typeface = getTypefaceFromCache(fontFamily, fontStyle); - if (typeface == nullptr) { - typeface = MakeTypefaceWithName(fontFamily, fontStyle); - } - if (typeface == nullptr) { - auto index = fontFamily.find(' '); - if (index != std::string::npos) { - auto family = fontFamily.substr(0, index); - auto style = fontFamily.substr(index + 1); - typeface = MakeTypefaceWithName(family, style); + const std::string& fontStyle) { + std::shared_ptr typeface = getTypefaceFromCache(fontFamily, fontStyle); + if (typeface == nullptr) { + typeface = MakeTypefaceWithName(fontFamily, fontStyle); } - } - return typeface; + if (typeface == nullptr) { + auto index = fontFamily.find(' '); + if (index != std::string::npos) { + auto family = fontFamily.substr(0, index); + auto style = fontFamily.substr(index + 1); + typeface = MakeTypefaceWithName(family, style); + } + } + return typeface; } std::shared_ptr FontManager::getFallbackTypeface(const std::string& name, - GlyphID* glyphID) { - std::lock_guard autoLock(locker); - for (auto& holder : fallbackFontList) { - auto typeface = holder->getTypeface(); - if (typeface != nullptr) { - *glyphID = typeface->getGlyphID(name); - if (*glyphID != 0) { - return typeface; - } + GlyphID* glyphID) { + std::lock_guard autoLock(locker); + for (auto& holder : fallbackFontList) { + auto typeface = holder->getTypeface(); + if (typeface != nullptr) { + *glyphID = typeface->getGlyphID(name); + if (*glyphID != 0) { + return typeface; + } + } } - } - return Typeface::MakeDefault(); + return Typeface::MakeDefault(); } void FontManager::setFallbackFontNames(const std::vector& fontNames) { - std::lock_guard autoLock(locker); - fallbackFontList.clear(); - for (auto& fontFamily : fontNames) { - auto holder = TypefaceHolder::MakeFromName(fontFamily, ""); - fallbackFontList.push_back(holder); - } + std::lock_guard autoLock(locker); + fallbackFontList.clear(); + for (auto& fontFamily : fontNames) { + auto holder = TypefaceHolder::MakeFromName(fontFamily, ""); + fallbackFontList.push_back(holder); + } } void FontManager::setFallbackFontPaths(const std::vector& fontPaths, const std::vector& ttcIndices) { - std::lock_guard autoLock(locker); - fallbackFontList.clear(); - int index = 0; - for (auto& fontPath : fontPaths) { - auto holder = TypefaceHolder::MakeFromFile(fontPath, ttcIndices[index]); - fallbackFontList.push_back(holder); - index++; - } + std::lock_guard autoLock(locker); + fallbackFontList.clear(); + int index = 0; + for (auto& fontPath : fontPaths) { + auto holder = TypefaceHolder::MakeFromFile(fontPath, ttcIndices[index]); + fallbackFontList.push_back(holder); + index++; + } } std::shared_ptr FontManager::getTypefaceFromCache(const std::string& fontFamily, - const std::string& fontStyle) { - std::lock_guard autoLock(locker); - auto result = registeredFontMap.find(PAGFontRegisterKey(fontFamily, fontStyle)); - if (result != registeredFontMap.end()) { - return result->second; - } - return nullptr; + const std::string& fontStyle) { + std::lock_guard autoLock(locker); + auto result = registeredFontMap.find(PAGFontRegisterKey(fontFamily, fontStyle)); + if (result != registeredFontMap.end()) { + return result->second; + } + return nullptr; } static FontManager fontManager = {}; std::shared_ptr FontManager::GetTypefaceWithoutFallback(const std::string& fontFamily, - const std::string& fontStyle) { - static bool initialized = Platform::Current()->registerFallbackFonts(); - USE(initialized); - return fontManager.getTypefaceWithoutFallback(fontFamily, fontStyle); + const std::string& fontStyle) { + static bool initialized = Platform::Current()->registerFallbackFonts(); + USE(initialized); + return fontManager.getTypefaceWithoutFallback(fontFamily, fontStyle); } std::shared_ptr FontManager::GetFallbackTypeface(const std::string& name, - GlyphID* glyphID) { - return fontManager.getFallbackTypeface(name, glyphID); + GlyphID* glyphID) { + return fontManager.getFallbackTypeface(name, glyphID); } PAGFont FontManager::RegisterFont(const std::string& fontPath, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - return fontManager.registerFont(fontPath, ttcIndex, fontFamily, fontStyle); + return fontManager.registerFont(fontPath, ttcIndex, fontFamily, fontStyle); } PAGFont FontManager::RegisterFont(const void* data, size_t length, int ttcIndex, const std::string& fontFamily, const std::string& fontStyle) { - return fontManager.registerFont(data, length, ttcIndex, fontFamily, fontStyle); + return fontManager.registerFont(data, length, ttcIndex, fontFamily, fontStyle); } void FontManager::UnregisterFont(const PAGFont& font) { - return fontManager.unregisterFont(font); + return fontManager.unregisterFont(font); } void FontManager::SetFallbackFontNames(const std::vector& fontNames) { - fontManager.setFallbackFontNames(fontNames); + fontManager.setFallbackFontNames(fontNames); } void FontManager::SetFallbackFontPaths(const std::vector& fontPaths, const std::vector& ttcIndices) { - fontManager.setFallbackFontPaths(fontPaths, ttcIndices); + fontManager.setFallbackFontPaths(fontPaths, ttcIndices); } } // namespace pag diff --git a/src/rendering/graphics/FontManager.h b/src/rendering/graphics/FontManager.h index e82470c959..64125d0fa9 100644 --- a/src/rendering/graphics/FontManager.h +++ b/src/rendering/graphics/FontManager.h @@ -26,74 +26,74 @@ namespace pag { class TypefaceHolder { - public: - static std::shared_ptr MakeFromName(const std::string& fontFamily, - const std::string& fontStyle); +public: + static std::shared_ptr MakeFromName(const std::string& fontFamily, + const std::string& fontStyle); - static std::shared_ptr MakeFromFile(const std::string& fontPath, - int ttcIndex = 0); + static std::shared_ptr MakeFromFile(const std::string& fontPath, + int ttcIndex = 0); - std::shared_ptr getTypeface(); + std::shared_ptr getTypeface(); - private: - std::string fontFamily; - std::string fontStyle; - std::string fontPath; - int ttcIndex = 0; - std::shared_ptr typeface = nullptr; +private: + std::string fontFamily; + std::string fontStyle; + std::string fontPath; + int ttcIndex = 0; + std::shared_ptr typeface = nullptr; }; class FontManager { - public: - static std::shared_ptr GetTypefaceWithoutFallback(const std::string& fontFamily, - const std::string& fontStyle); - static std::shared_ptr GetFallbackTypeface(const std::string& name, GlyphID* glyphID); +public: + static std::shared_ptr GetTypefaceWithoutFallback(const std::string& fontFamily, + const std::string& fontStyle); + static std::shared_ptr GetFallbackTypeface(const std::string& name, GlyphID* glyphID); - static PAGFont RegisterFont(const std::string& fontPath, int ttcIndex, - const std::string& fontFamily, const std::string& fontStyle); + static PAGFont RegisterFont(const std::string& fontPath, int ttcIndex, + const std::string& fontFamily, const std::string& fontStyle); - static PAGFont RegisterFont(const void* data, size_t length, int ttcIndex, - const std::string& fontFamily, const std::string& fontStyle); + static PAGFont RegisterFont(const void* data, size_t length, int ttcIndex, + const std::string& fontFamily, const std::string& fontStyle); - static void UnregisterFont(const PAGFont& font); + static void UnregisterFont(const PAGFont& font); - static void SetFallbackFontNames(const std::vector& fontNames); + static void SetFallbackFontNames(const std::vector& fontNames); - static void SetFallbackFontPaths(const std::vector& fontPaths, - const std::vector& ttcIndices); + static void SetFallbackFontPaths(const std::vector& fontPaths, + const std::vector& ttcIndices); - ~FontManager(); + ~FontManager(); - private: - PAGFont registerFont(const std::string& fontPath, int ttcIndex = 0, - const std::string& fontFamily = "", const std::string& fontStyle = ""); +private: + PAGFont registerFont(const std::string& fontPath, int ttcIndex = 0, + const std::string& fontFamily = "", const std::string& fontStyle = ""); - PAGFont registerFont(const void* data, size_t length, int ttcIndex = 0, - const std::string& fontFamily = "", const std::string& fontStyle = ""); + PAGFont registerFont(const void* data, size_t length, int ttcIndex = 0, + const std::string& fontFamily = "", const std::string& fontStyle = ""); - PAGFont registerFont(const PAGFont& font, std::shared_ptr typeface, - const std::string& fontFamily = "", const std::string& fontStyle = ""); + PAGFont registerFont(const PAGFont& font, std::shared_ptr typeface, + const std::string& fontFamily = "", const std::string& fontStyle = ""); - void unregisterFont(const PAGFont& font); + void unregisterFont(const PAGFont& font); - std::shared_ptr getTypefaceWithoutFallback(const std::string& fontFamily, - const std::string& fontStyle); + std::shared_ptr getTypefaceWithoutFallback(const std::string& fontFamily, + const std::string& fontStyle); - std::shared_ptr getFallbackTypeface(const std::string& name, GlyphID* glyphID); + std::shared_ptr getFallbackTypeface(const std::string& name, GlyphID* glyphID); - void setFallbackFontNames(const std::vector& fontNames); + void setFallbackFontNames(const std::vector& fontNames); - void setFallbackFontPaths(const std::vector& fontPaths, - const std::vector& ttcIndices); + void setFallbackFontPaths(const std::vector& fontPaths, + const std::vector& ttcIndices); - std::unordered_map> registeredFontMap; - std::vector> fallbackFontList; - std::mutex locker = {}; + std::unordered_map> registeredFontMap; + std::vector> fallbackFontList; + std::mutex locker = {}; - std::shared_ptr getTypefaceFromCache(const std::string& fontFamily, - const std::string& fontStyle); + std::shared_ptr getTypefaceFromCache(const std::string& fontFamily, + const std::string& fontStyle); - friend class PAGFont; + friend class PAGFont; }; } // namespace pag diff --git a/src/rendering/graphics/Glyph.cpp b/src/rendering/graphics/Glyph.cpp index 68a4064493..66711b64fb 100644 --- a/src/rendering/graphics/Glyph.cpp +++ b/src/rendering/graphics/Glyph.cpp @@ -22,106 +22,107 @@ namespace pag { std::vector Glyph::BuildFromText(const std::string& text, const TextPaint& textPaint) { - Font textFont = {}; - textFont.setFauxBold(textPaint.fauxBold); - textFont.setFauxItalic(textPaint.fauxItalic); - textFont.setSize(textPaint.fontSize); - auto typeface = - FontManager::GetTypefaceWithoutFallback(textPaint.fontFamily, textPaint.fontStyle); - bool hasTypeface = typeface != nullptr; - std::vector glyphList; - const char* textStart = &(text[0]); - const char* textStop = textStart + text.size(); - while (textStart < textStop) { - auto oldPosition = textStart; - UTF8Text::NextChar(&textStart); - auto length = textStart - oldPosition; - auto name = std::string(oldPosition, length); - GlyphID glyphId = 0; - if (hasTypeface) { - glyphId = typeface->getGlyphID(name); - if (glyphId != 0) { - textFont.setTypeface(typeface); - } + Font textFont = {}; + textFont.setFauxBold(textPaint.fauxBold); + textFont.setFauxItalic(textPaint.fauxItalic); + textFont.setSize(textPaint.fontSize); + auto typeface = + FontManager::GetTypefaceWithoutFallback(textPaint.fontFamily, textPaint.fontStyle); + bool hasTypeface = typeface != nullptr; + std::vector glyphList; + const char* textStart = &(text[0]); + const char* textStop = textStart + text.size(); + while (textStart < textStop) { + auto oldPosition = textStart; + UTF8Text::NextChar(&textStart); + auto length = textStart - oldPosition; + auto name = std::string(oldPosition, length); + GlyphID glyphId = 0; + if (hasTypeface) { + glyphId = typeface->getGlyphID(name); + if (glyphId != 0) { + textFont.setTypeface(typeface); + } + } + if (glyphId == 0) { + auto fallbackTypeface = FontManager::GetFallbackTypeface(name, &glyphId); + textFont.setTypeface(fallbackTypeface); + } + auto glyph = std::shared_ptr(new Glyph(glyphId, name, textFont, textPaint)); + glyphList.push_back(glyph); } - if (glyphId == 0) { - auto fallbackTypeface = FontManager::GetFallbackTypeface(name, &glyphId); - textFont.setTypeface(fallbackTypeface); - } - auto glyph = std::shared_ptr(new Glyph(glyphId, name, textFont, textPaint)); - glyphList.push_back(glyph); - } - return glyphList; + return glyphList; } Glyph::Glyph(GlyphID glyphId, const std::string& charName, const Font& textFont, const TextPaint& textPaint) : glyphId(glyphId), textFont(textFont) { - name = charName; - _isVertical = textPaint.isVertical; - textStyle = textPaint.style; - strokeOverFill = textPaint.strokeOverFill; - fillColor = textPaint.fillColor; - strokeColor = textPaint.strokeColor; - strokeWidth = textPaint.strokeWidth; - auto metrics = textFont.getMetrics(); - ascent = metrics.ascent; - descent = metrics.descent; - advance = textFont.getGlyphAdvance(glyphId); - bounds = textFont.getGlyphBounds(glyphId); - if (charName == " ") { - // 空格字符测量的 bounds 比较异常偏上,本身也不可见,这里直接按字幕 A 的上下边界调整一下。 - auto AGlyphID = textFont.getGlyphID("A"); - if (AGlyphID > 0) { - auto ABounds = textFont.getGlyphBounds(AGlyphID); - bounds.top = ABounds.top; - bounds.bottom = ABounds.bottom; + name = charName; + _isVertical = textPaint.isVertical; + textStyle = textPaint.style; + strokeOverFill = textPaint.strokeOverFill; + fillColor = textPaint.fillColor; + strokeColor = textPaint.strokeColor; + strokeWidth = textPaint.strokeWidth; + auto metrics = textFont.getMetrics(); + ascent = metrics.ascent; + descent = metrics.descent; + advance = textFont.getGlyphAdvance(glyphId); + bounds = textFont.getGlyphBounds(glyphId); + if (charName == " ") { + // 空格字符测量的 bounds 比较异常偏上,本身也不可见,这里直接按字幕 A 的上下边界调整一下。 + auto AGlyphID = textFont.getGlyphID("A"); + if (AGlyphID > 0) { + auto ABounds = textFont.getGlyphBounds(AGlyphID); + bounds.top = ABounds.top; + bounds.bottom = ABounds.bottom; + } } - } - if (textPaint.isVertical) { - if (name.size() == 1) { - // 字母,数字,标点等字符旋转 90° 绘制,原先的水平 baseline 转为垂直 baseline, - // 并水平向左偏移半个大写字母高度。 - extraMatrix.setRotate(90); - auto offsetX = (metrics.capHeight + metrics.xHeight) * 0.25f; - extraMatrix.postTranslate(-offsetX, 0); - ascent += offsetX; - descent += offsetX; - } else { - auto offset = textFont.getGlyphVerticalOffset(glyphId); - extraMatrix.postTranslate(offset.x, offset.y); - auto width = advance; - advance = textFont.getGlyphAdvance(glyphId, true); - ascent = -width * 0.5f; - descent = width * 0.5f; + if (textPaint.isVertical) { + if (name.size() == 1) { + // 字母,数字,标点等字符旋转 90° 绘制,原先的水平 baseline 转为垂直 baseline, + // 并水平向左偏移半个大写字母高度。 + extraMatrix.setRotate(90); + auto offsetX = (metrics.capHeight + metrics.xHeight) * 0.25f; + extraMatrix.postTranslate(-offsetX, 0); + ascent += offsetX; + descent += offsetX; + } else { + auto offset = textFont.getGlyphVerticalOffset(glyphId); + extraMatrix.postTranslate(offset.x, offset.y); + auto width = advance; + advance = textFont.getGlyphAdvance(glyphId, true); + ascent = -width * 0.5f; + descent = width * 0.5f; + } + extraMatrix.mapRect(&bounds); } - extraMatrix.mapRect(&bounds); - } } void Glyph::computeStyleKey(BytesKey* styleKey) const { - auto m = getTotalMatrix(); - styleKey->write(m.getScaleX()); - styleKey->write(m.getSkewX()); - styleKey->write(m.getSkewY()); - styleKey->write(m.getScaleY()); - uint8_t fillValues[] = {fillColor.red, fillColor.green, fillColor.blue, alpha}; - styleKey->write(fillValues); - uint8_t strokeValues[] = {strokeColor.red, strokeColor.green, strokeColor.blue, - static_cast(textStyle)}; - styleKey->write(strokeValues); - styleKey->write(strokeWidth); - styleKey->write(textFont.getTypeface()->uniqueID()); + auto m = getTotalMatrix(); + styleKey->write(m.getScaleX()); + styleKey->write(m.getSkewX()); + styleKey->write(m.getSkewY()); + styleKey->write(m.getScaleY()); + uint8_t fillValues[] = {fillColor.red, fillColor.green, fillColor.blue, alpha}; + styleKey->write(fillValues); + uint8_t strokeValues[] = {strokeColor.red, strokeColor.green, strokeColor.blue, + static_cast(textStyle) + }; + styleKey->write(strokeValues); + styleKey->write(strokeWidth); + styleKey->write(textFont.getTypeface()->uniqueID()); } bool Glyph::isVisible() const { - return matrix.invertible() && alpha != Transparent && !bounds.isEmpty(); + return matrix.invertible() && alpha != Transparent && !bounds.isEmpty(); } Matrix Glyph::getTotalMatrix() const { - auto m = extraMatrix; - m.postConcat(matrix); - return m; + auto m = extraMatrix; + m.postConcat(matrix); + return m; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/graphics/Glyph.h b/src/rendering/graphics/Glyph.h index 0fd2546b65..1d56893f81 100644 --- a/src/rendering/graphics/Glyph.h +++ b/src/rendering/graphics/Glyph.h @@ -33,17 +33,17 @@ enum class TextStyle { Fill, Stroke, StrokeAndFill }; * Defines attributes for drawing text. */ struct TextPaint { - TextStyle style = TextStyle::Fill; - Color fillColor = Black; - Color strokeColor = Black; - float strokeWidth = 0; - bool strokeOverFill = true; - std::string fontFamily; - std::string fontStyle; - float fontSize = 24; - bool fauxBold = false; - bool fauxItalic = false; - bool isVertical = false; + TextStyle style = TextStyle::Fill; + Color fillColor = Black; + Color strokeColor = Black; + float strokeWidth = 0; + bool strokeOverFill = true; + std::string fontFamily; + std::string fontStyle; + float fontSize = 24; + bool fauxBold = false; + bool fauxItalic = false; + bool isVertical = false; }; class Glyph; @@ -54,197 +54,197 @@ typedef std::shared_ptr GlyphHandle; * Glyph represents a single character for drawing. */ class Glyph { - public: - static std::vector BuildFromText(const std::string& text, - const TextPaint& textPaint); - - virtual ~Glyph() = default; - - /** - * Called by the Text::MakeFrom() method to merge the draw calls of glyphs with the same style. - * Return false if this glyph is not visible. - */ - void computeStyleKey(BytesKey* styleKey) const; - - /** - * Returns the Font object associated with this Glyph. - */ - Font getFont() const { - return textFont; - } - - /** - * Returns the id of this glyph in associated typeface. - */ - GlyphID getGlyphID() const { - return glyphId; - } - - /** - * Returns true if this glyph is visible for drawing. - */ - bool isVisible() const; - - /** - * Returns true if this glyph is for vertical text layouts. - */ - bool isVertical() const { - return _isVertical; - } - - /** - * Returns name of this glyph in utf8. - */ - std::string getName() const { - return name; - } - - /** - * Returns the advance for this glyph. - */ - float getAdvance() const { - return advance; - } - - /** - * Returns the recommended distance to reserve above baseline - */ - float getAscent() const { - return ascent; - } - - /** - * Returns the recommended distance to reserve below baseline - */ - float getDescent() const { - return descent; - } - - /** - * Returns the bounding box relative to (0, 0) of this glyph. Returned bounds may be larger than - * the exact bounds of this glyph. - */ - const Rect& getBounds() const { - return bounds; - } - - /** - * Returns the matrix for this glyph. - */ - Matrix getMatrix() const { - return matrix; - } - - /** - * Replaces transformation with specified matrix. - */ - void setMatrix(const Matrix& m) { - matrix = m; - } - - /** - * Returns the text style for this glyph. - */ - TextStyle getStyle() const { - return textStyle; - } - - /** - * Sets the text style for this glyph. - */ - void setStyle(TextStyle style) { - textStyle = style; - } - - /** - * Returns true if stroke is drawn on top of fill. - */ - bool getStrokeOverFill() const { - return strokeOverFill; - } - - /** - * Retrieves alpha from the color used when stroking and filling. - */ - Opacity getAlpha() const { - return alpha; - } - - /** - * Replaces alpha of the color used when stroking and filling, leaving RGB unchanged. - */ - void setAlpha(Opacity opacity) { - alpha = opacity; - } - - /** - * Retrieves RGB from the color used when filling. - */ - Color getFillColor() const { - return fillColor; - } - - /** - * Replaces RGB from the color used when filling. - */ - void setFillColor(const Color& color) { - fillColor = color; - } - - /** - * Retrieves RGB from the color used when stroking. - */ - Color getStrokeColor() const { - return strokeColor; - } - - /** - * Replaces RGB from the color used when stroking. - */ - void setStrokeColor(const Color& color) { - strokeColor = color; - } - - /** - * Returns the thickness of the pen used to outline the glyph. - */ - float getStrokeWidth() const { - return strokeWidth; - } - - /** - * Replaces the thickness of the pen used to outline the glyph. - */ - void setStrokeWidth(float width) { - strokeWidth = width; - } - - /** - * Returns the total matrix of this glyph which contains the style matrix. - */ - Matrix getTotalMatrix() const; - - private: - GlyphID glyphId = 0; - Font textFont = {}; - // read only attributes: - float advance = 0; - float ascent = 0; - float descent = 0; - Rect bounds = Rect::MakeEmpty(); - std::string name; - bool _isVertical = false; - bool strokeOverFill = true; - Matrix extraMatrix = Matrix::I(); // for vertical text or fauxItalic. - // writable attributes: - Matrix matrix = Matrix::I(); - TextStyle textStyle = TextStyle::Fill; - Opacity alpha = Opaque; - Color fillColor = Black; - Color strokeColor = Black; - float strokeWidth = 0; - - Glyph(GlyphID glyphId, const std::string& name, const Font& textFont, const TextPaint& textPaint); +public: + static std::vector BuildFromText(const std::string& text, + const TextPaint& textPaint); + + virtual ~Glyph() = default; + + /** + * Called by the Text::MakeFrom() method to merge the draw calls of glyphs with the same style. + * Return false if this glyph is not visible. + */ + void computeStyleKey(BytesKey* styleKey) const; + + /** + * Returns the Font object associated with this Glyph. + */ + Font getFont() const { + return textFont; + } + + /** + * Returns the id of this glyph in associated typeface. + */ + GlyphID getGlyphID() const { + return glyphId; + } + + /** + * Returns true if this glyph is visible for drawing. + */ + bool isVisible() const; + + /** + * Returns true if this glyph is for vertical text layouts. + */ + bool isVertical() const { + return _isVertical; + } + + /** + * Returns name of this glyph in utf8. + */ + std::string getName() const { + return name; + } + + /** + * Returns the advance for this glyph. + */ + float getAdvance() const { + return advance; + } + + /** + * Returns the recommended distance to reserve above baseline + */ + float getAscent() const { + return ascent; + } + + /** + * Returns the recommended distance to reserve below baseline + */ + float getDescent() const { + return descent; + } + + /** + * Returns the bounding box relative to (0, 0) of this glyph. Returned bounds may be larger than + * the exact bounds of this glyph. + */ + const Rect& getBounds() const { + return bounds; + } + + /** + * Returns the matrix for this glyph. + */ + Matrix getMatrix() const { + return matrix; + } + + /** + * Replaces transformation with specified matrix. + */ + void setMatrix(const Matrix& m) { + matrix = m; + } + + /** + * Returns the text style for this glyph. + */ + TextStyle getStyle() const { + return textStyle; + } + + /** + * Sets the text style for this glyph. + */ + void setStyle(TextStyle style) { + textStyle = style; + } + + /** + * Returns true if stroke is drawn on top of fill. + */ + bool getStrokeOverFill() const { + return strokeOverFill; + } + + /** + * Retrieves alpha from the color used when stroking and filling. + */ + Opacity getAlpha() const { + return alpha; + } + + /** + * Replaces alpha of the color used when stroking and filling, leaving RGB unchanged. + */ + void setAlpha(Opacity opacity) { + alpha = opacity; + } + + /** + * Retrieves RGB from the color used when filling. + */ + Color getFillColor() const { + return fillColor; + } + + /** + * Replaces RGB from the color used when filling. + */ + void setFillColor(const Color& color) { + fillColor = color; + } + + /** + * Retrieves RGB from the color used when stroking. + */ + Color getStrokeColor() const { + return strokeColor; + } + + /** + * Replaces RGB from the color used when stroking. + */ + void setStrokeColor(const Color& color) { + strokeColor = color; + } + + /** + * Returns the thickness of the pen used to outline the glyph. + */ + float getStrokeWidth() const { + return strokeWidth; + } + + /** + * Replaces the thickness of the pen used to outline the glyph. + */ + void setStrokeWidth(float width) { + strokeWidth = width; + } + + /** + * Returns the total matrix of this glyph which contains the style matrix. + */ + Matrix getTotalMatrix() const; + +private: + GlyphID glyphId = 0; + Font textFont = {}; + // read only attributes: + float advance = 0; + float ascent = 0; + float descent = 0; + Rect bounds = Rect::MakeEmpty(); + std::string name; + bool _isVertical = false; + bool strokeOverFill = true; + Matrix extraMatrix = Matrix::I(); // for vertical text or fauxItalic. + // writable attributes: + Matrix matrix = Matrix::I(); + TextStyle textStyle = TextStyle::Fill; + Opacity alpha = Opaque; + Color fillColor = Black; + Color strokeColor = Black; + float strokeWidth = 0; + + Glyph(GlyphID glyphId, const std::string& name, const Font& textFont, const TextPaint& textPaint); }; } // namespace pag diff --git a/src/rendering/graphics/Graphic.cpp b/src/rendering/graphics/Graphic.cpp index 8b12690603..1ca16ea1c5 100644 --- a/src/rendering/graphics/Graphic.cpp +++ b/src/rendering/graphics/Graphic.cpp @@ -22,273 +22,273 @@ namespace pag { class ComposeGraphic : public Graphic { - public: - GraphicType type() const override { - return GraphicType::Compose; - } - - virtual std::shared_ptr mergeWith(const Matrix&) const { - return nullptr; - } - - virtual std::shared_ptr mergeWith(const Modifier*) const { - return nullptr; - } +public: + GraphicType type() const override { + return GraphicType::Compose; + } + + virtual std::shared_ptr mergeWith(const Matrix&) const { + return nullptr; + } + + virtual std::shared_ptr mergeWith(const Modifier*) const { + return nullptr; + } }; //===================================== MatrixGraphic ============================================== class MatrixGraphic : public ComposeGraphic { - public: - MatrixGraphic(std::shared_ptr graphic, const Matrix& matrix) - : graphic(std::move(graphic)), matrix(matrix) { - } - - void measureBounds(Rect* bounds) const override; - bool hitTest(RenderCache* cache, float x, float y) override; - bool getPath(Path* path) const override; - void prepare(RenderCache* cache) const override; - void draw(Canvas* canvas, RenderCache* cache) const override; - std::shared_ptr mergeWith(const Matrix& matrix) const override; - - protected: - std::shared_ptr graphic = nullptr; - Matrix matrix = {}; +public: + MatrixGraphic(std::shared_ptr graphic, const Matrix& matrix) + : graphic(std::move(graphic)), matrix(matrix) { + } + + void measureBounds(Rect* bounds) const override; + bool hitTest(RenderCache* cache, float x, float y) override; + bool getPath(Path* path) const override; + void prepare(RenderCache* cache) const override; + void draw(Canvas* canvas, RenderCache* cache) const override; + std::shared_ptr mergeWith(const Matrix& matrix) const override; + +protected: + std::shared_ptr graphic = nullptr; + Matrix matrix = {}; }; std::shared_ptr Graphic::MakeCompose(std::shared_ptr graphic, - const Matrix& matrix) { - if (graphic == nullptr || !matrix.invertible()) { - return nullptr; - } - if (matrix.isIdentity()) { - return graphic; - } - if (graphic->type() == GraphicType::Compose) { - auto result = std::static_pointer_cast(graphic)->mergeWith(matrix); - if (result) { - return result; + const Matrix& matrix) { + if (graphic == nullptr || !matrix.invertible()) { + return nullptr; + } + if (matrix.isIdentity()) { + return graphic; + } + if (graphic->type() == GraphicType::Compose) { + auto result = std::static_pointer_cast(graphic)->mergeWith(matrix); + if (result) { + return result; + } } - } - return std::make_shared(graphic, matrix); + return std::make_shared(graphic, matrix); } void MatrixGraphic::measureBounds(Rect* bounds) const { - graphic->measureBounds(bounds); - matrix.mapRect(bounds); + graphic->measureBounds(bounds); + matrix.mapRect(bounds); } bool MatrixGraphic::hitTest(RenderCache* cache, float x, float y) { - Point local = {x, y}; - if (!MapPointInverted(matrix, &local)) { - return false; - } - return graphic->hitTest(cache, local.x, local.y); + Point local = {x, y}; + if (!MapPointInverted(matrix, &local)) { + return false; + } + return graphic->hitTest(cache, local.x, local.y); } bool MatrixGraphic::getPath(Path* path) const { - Path fillPath = {}; - if (!graphic->getPath(&fillPath)) { - return false; - } - fillPath.transform(matrix); - path->addPath(fillPath); - return true; + Path fillPath = {}; + if (!graphic->getPath(&fillPath)) { + return false; + } + fillPath.transform(matrix); + path->addPath(fillPath); + return true; } void MatrixGraphic::prepare(RenderCache* cache) const { - graphic->prepare(cache); + graphic->prepare(cache); } void MatrixGraphic::draw(Canvas* canvas, RenderCache* cache) const { - canvas->save(); - canvas->concat(matrix); - graphic->draw(canvas, cache); - canvas->restore(); + canvas->save(); + canvas->concat(matrix); + graphic->draw(canvas, cache); + canvas->restore(); } std::shared_ptr MatrixGraphic::mergeWith(const Matrix& m) const { - auto totalMatrix = matrix; - totalMatrix.postConcat(m); - if (totalMatrix.isIdentity()) { - return graphic; - } - return std::make_shared(graphic, totalMatrix); + auto totalMatrix = matrix; + totalMatrix.postConcat(m); + if (totalMatrix.isIdentity()) { + return graphic; + } + return std::make_shared(graphic, totalMatrix); } //===================================== MatrixGraphic ============================================== //===================================== LayerGraphic =============================================== class LayerGraphic : public ComposeGraphic { - public: - explicit LayerGraphic(std::vector> contents) - : contents(std::move(contents)) { - } - - void measureBounds(Rect* bounds) const override; - bool hitTest(RenderCache* cache, float x, float y) override; - bool getPath(Path* path) const override; - void prepare(RenderCache* cache) const override; - void draw(Canvas* canvas, RenderCache* cache) const override; - std::shared_ptr mergeWith(const Matrix& matrix) const override; - - private: - std::vector> contents = {}; +public: + explicit LayerGraphic(std::vector> contents) + : contents(std::move(contents)) { + } + + void measureBounds(Rect* bounds) const override; + bool hitTest(RenderCache* cache, float x, float y) override; + bool getPath(Path* path) const override; + void prepare(RenderCache* cache) const override; + void draw(Canvas* canvas, RenderCache* cache) const override; + std::shared_ptr mergeWith(const Matrix& matrix) const override; + +private: + std::vector> contents = {}; }; std::shared_ptr Graphic::MakeCompose(std::vector> contents) { - std::vector> graphics = {}; - for (auto& content : contents) { - if (content == nullptr) { - continue; + std::vector> graphics = {}; + for (auto& content : contents) { + if (content == nullptr) { + continue; + } + graphics.push_back(content); + } + if (graphics.empty()) { + return nullptr; + } + if (graphics.size() == 1) { + return graphics[0]; } - graphics.push_back(content); - } - if (graphics.empty()) { - return nullptr; - } - if (graphics.size() == 1) { - return graphics[0]; - } - return std::make_shared(graphics); + return std::make_shared(graphics); } void LayerGraphic::measureBounds(Rect* bounds) const { - bounds->setEmpty(); - for (auto& content : contents) { - Rect rect = Rect::MakeEmpty(); - content->measureBounds(&rect); - bounds->join(rect); - } + bounds->setEmpty(); + for (auto& content : contents) { + Rect rect = Rect::MakeEmpty(); + content->measureBounds(&rect); + bounds->join(rect); + } } bool LayerGraphic::hitTest(RenderCache* cache, float x, float y) { - return std::any_of(contents.begin(), contents.end(), [=](std::shared_ptr& graphic) { - return graphic->hitTest(cache, x, y); - }); + return std::any_of(contents.begin(), contents.end(), [=](std::shared_ptr& graphic) { + return graphic->hitTest(cache, x, y); + }); } bool LayerGraphic::getPath(Path* path) const { - Path fillPath = {}; - for (auto& content : contents) { - Path temp = {}; - if (!content->getPath(&temp)) { - return false; + Path fillPath = {}; + for (auto& content : contents) { + Path temp = {}; + if (!content->getPath(&temp)) { + return false; + } + fillPath.addPath(temp); } - fillPath.addPath(temp); - } - path->addPath(fillPath); - return true; + path->addPath(fillPath); + return true; } void LayerGraphic::prepare(RenderCache* cache) const { - for (auto& content : contents) { - content->prepare(cache); - } + for (auto& content : contents) { + content->prepare(cache); + } } void LayerGraphic::draw(Canvas* canvas, RenderCache* cache) const { - for (auto& content : contents) { - canvas->save(); - content->draw(canvas, cache); - canvas->restore(); - } + for (auto& content : contents) { + canvas->save(); + content->draw(canvas, cache); + canvas->restore(); + } } std::shared_ptr LayerGraphic::mergeWith(const Matrix& m) const { - std::vector> newContents = {}; - for (auto& graphic : contents) { - if (graphic->type() != GraphicType::Compose) { - return nullptr; - } - auto result = static_cast(graphic.get())->mergeWith(m); - if (!result) { - return nullptr; + std::vector> newContents = {}; + for (auto& graphic : contents) { + if (graphic->type() != GraphicType::Compose) { + return nullptr; + } + auto result = static_cast(graphic.get())->mergeWith(m); + if (!result) { + return nullptr; + } + newContents.push_back(result); } - newContents.push_back(result); - } - return std::make_shared(newContents); + return std::make_shared(newContents); } //===================================== LayerGraphic =============================================== //==================================== ModifierGraphic ============================================= class ModifierGraphic : public ComposeGraphic { - public: - ModifierGraphic(std::shared_ptr graphic, std::shared_ptr modifier) - : graphic(std::move(graphic)), modifier(std::move(modifier)) { - } - - void measureBounds(Rect* bounds) const override; - bool hitTest(RenderCache* cache, float x, float y) override; - bool getPath(Path* path) const override; - void prepare(RenderCache* cache) const override; - void draw(Canvas* canvas, RenderCache* cache) const override; - std::shared_ptr mergeWith(const Modifier* target) const override; - - private: - std::shared_ptr graphic = nullptr; - std::shared_ptr modifier = nullptr; +public: + ModifierGraphic(std::shared_ptr graphic, std::shared_ptr modifier) + : graphic(std::move(graphic)), modifier(std::move(modifier)) { + } + + void measureBounds(Rect* bounds) const override; + bool hitTest(RenderCache* cache, float x, float y) override; + bool getPath(Path* path) const override; + void prepare(RenderCache* cache) const override; + void draw(Canvas* canvas, RenderCache* cache) const override; + std::shared_ptr mergeWith(const Modifier* target) const override; + +private: + std::shared_ptr graphic = nullptr; + std::shared_ptr modifier = nullptr; }; std::shared_ptr Graphic::MakeCompose(std::shared_ptr graphic, - std::shared_ptr modifier) { - if (modifier == nullptr) { - return graphic; - } - if (graphic == nullptr || modifier->isEmpty()) { - return nullptr; - } - if (graphic->type() == GraphicType::Compose) { - auto result = std::static_pointer_cast(graphic)->mergeWith(modifier.get()); - if (result) { - return result; + std::shared_ptr modifier) { + if (modifier == nullptr) { + return graphic; } - } - return std::make_shared(graphic, modifier); + if (graphic == nullptr || modifier->isEmpty()) { + return nullptr; + } + if (graphic->type() == GraphicType::Compose) { + auto result = std::static_pointer_cast(graphic)->mergeWith(modifier.get()); + if (result) { + return result; + } + } + return std::make_shared(graphic, modifier); } void ModifierGraphic::measureBounds(Rect* bounds) const { - graphic->measureBounds(bounds); - modifier->applyToBounds(bounds); + graphic->measureBounds(bounds); + modifier->applyToBounds(bounds); } bool ModifierGraphic::hitTest(RenderCache* cache, float x, float y) { - if (!modifier->hitTest(cache, x, y)) { - return false; - } - return graphic->hitTest(cache, x, y); + if (!modifier->hitTest(cache, x, y)) { + return false; + } + return graphic->hitTest(cache, x, y); } bool ModifierGraphic::getPath(Path* path) const { - Path fillPath = {}; - if (!graphic->getPath(&fillPath)) { - return false; - } - if (!modifier->applyToPath(&fillPath)) { - return false; - } - path->addPath(fillPath); - return true; + Path fillPath = {}; + if (!graphic->getPath(&fillPath)) { + return false; + } + if (!modifier->applyToPath(&fillPath)) { + return false; + } + path->addPath(fillPath); + return true; } void ModifierGraphic::prepare(RenderCache* cache) const { - modifier->prepare(cache); - graphic->prepare(cache); + modifier->prepare(cache); + graphic->prepare(cache); } void ModifierGraphic::draw(Canvas* canvas, RenderCache* cache) const { - canvas->save(); - modifier->applyToGraphic(canvas, cache, graphic); - canvas->restore(); + canvas->save(); + modifier->applyToGraphic(canvas, cache, graphic); + canvas->restore(); } std::shared_ptr ModifierGraphic::mergeWith(const Modifier* target) const { - if (target == nullptr || modifier->type() != target->type()) { - return nullptr; - } - auto newModifier = modifier->mergeWith(target); - if (newModifier == nullptr) { - return nullptr; - } - return std::make_shared(graphic, newModifier); + if (target == nullptr || modifier->type() != target->type()) { + return nullptr; + } + auto newModifier = modifier->mergeWith(target); + if (newModifier == nullptr) { + return nullptr; + } + return std::make_shared(graphic, newModifier); } //==================================== ModifierGraphic ============================================= diff --git a/src/rendering/graphics/Graphic.h b/src/rendering/graphics/Graphic.h index 662a7cee65..a5efd19e98 100644 --- a/src/rendering/graphics/Graphic.h +++ b/src/rendering/graphics/Graphic.h @@ -27,11 +27,11 @@ namespace pag { enum class GraphicType { - Unknown, - Picture, - Shape, - Text, - Compose, + Unknown, + Picture, + Shape, + Text, + Compose, }; class Modifier; @@ -41,61 +41,61 @@ class Modifier; * Graphic is thread safe. */ class Graphic { - public: - /** - * Creates a compose Graphic with specified graphic and matrix. Returns nullptr if graphic is - * nullptr or matrix is invisible. - */ - static std::shared_ptr MakeCompose(std::shared_ptr graphic, - const Matrix& matrix); +public: + /** + * Creates a compose Graphic with specified graphic and matrix. Returns nullptr if graphic is + * nullptr or matrix is invisible. + */ + static std::shared_ptr MakeCompose(std::shared_ptr graphic, + const Matrix& matrix); - /** - * Creates a compose Graphic with graphic contents. Returns nullptr if contents are emtpy. - */ - static std::shared_ptr MakeCompose(std::vector> contents); + /** + * Creates a compose Graphic with graphic contents. Returns nullptr if contents are emtpy. + */ + static std::shared_ptr MakeCompose(std::vector> contents); - /** - * Creates a compose Graphic with specified graphic and modifier. Returns nullptr if graphic is - * nullptr. - */ - static std::shared_ptr MakeCompose(std::shared_ptr graphic, - std::shared_ptr modifier); + /** + * Creates a compose Graphic with specified graphic and modifier. Returns nullptr if graphic is + * nullptr. + */ + static std::shared_ptr MakeCompose(std::shared_ptr graphic, + std::shared_ptr modifier); - virtual ~Graphic() = default; + virtual ~Graphic() = default; - /** - * Measures the bounds of this Graphic. - */ - virtual void measureBounds(Rect* bounds) const = 0; + /** + * Measures the bounds of this Graphic. + */ + virtual void measureBounds(Rect* bounds) const = 0; - /** - * Evaluates the Graphic to see if it overlaps or intersects with the specified point. The point - * is in the coordinate space of the Graphic. This method always checks against the actual pixels - * of the Graphic. - */ - virtual bool hitTest(RenderCache* cache, float x, float y) = 0; + /** + * Evaluates the Graphic to see if it overlaps or intersects with the specified point. The point + * is in the coordinate space of the Graphic. This method always checks against the actual pixels + * of the Graphic. + */ + virtual bool hitTest(RenderCache* cache, float x, float y) = 0; - /** - * Returns the type of this graphic. - */ - virtual GraphicType type() const = 0; + /** + * Returns the type of this graphic. + */ + virtual GraphicType type() const = 0; - /** - * Gets a Path which is the filled equivalent of the Graphic contents. Returns false and - * leaves the path unchanged if the Graphic contents are not opaque or can not be converted to - * a path. - */ - virtual bool getPath(Path* path) const = 0; + /** + * Gets a Path which is the filled equivalent of the Graphic contents. Returns false and + * leaves the path unchanged if the Graphic contents are not opaque or can not be converted to + * a path. + */ + virtual bool getPath(Path* path) const = 0; - /** - * Prepares this graphic for next draw() call. It collects all CPU tasks in this Graphic and run - * them in parallel immediately. - */ - virtual void prepare(RenderCache* cache) const = 0; + /** + * Prepares this graphic for next draw() call. It collects all CPU tasks in this Graphic and run + * them in parallel immediately. + */ + virtual void prepare(RenderCache* cache) const = 0; - /** - * Draw this Graphic into specified Canvas. - */ - virtual void draw(Canvas* canvas, RenderCache* cache) const = 0; + /** + * Draw this Graphic into specified Canvas. + */ + virtual void draw(Canvas* canvas, RenderCache* cache) const = 0; }; } // namespace pag diff --git a/src/rendering/graphics/Modifier.cpp b/src/rendering/graphics/Modifier.cpp index 1a6049fe7e..b9c45c4c65 100644 --- a/src/rendering/graphics/Modifier.cpp +++ b/src/rendering/graphics/Modifier.cpp @@ -23,263 +23,263 @@ namespace pag { class BlendModifier : public Modifier { - public: - BlendModifier(Opacity alpha, Enum blendMode) : alpha(alpha), blendMode(blendMode) { - } +public: + BlendModifier(Opacity alpha, Enum blendMode) : alpha(alpha), blendMode(blendMode) { + } - ID type() const override { - static const auto TypeID = UniqueID::Next(); - return TypeID; - } + ID type() const override { + static const auto TypeID = UniqueID::Next(); + return TypeID; + } - bool isEmpty() const override { - return alpha == Transparent; - } + bool isEmpty() const override { + return alpha == Transparent; + } - bool hitTest(RenderCache* cache, float x, float y) const override; + bool hitTest(RenderCache* cache, float x, float y) const override; - void prepare(RenderCache*) const override { - } + void prepare(RenderCache*) const override { + } - void applyToBounds(Rect*) const override{}; + void applyToBounds(Rect*) const override {}; - bool applyToPath(Path*) const override { - return alpha == Opaque; // blendMode 只影响颜色,不改变形状或透明度,不影响 getPath 结果。 - } + bool applyToPath(Path*) const override { + return alpha == Opaque; // blendMode 只影响颜色,不改变形状或透明度,不影响 getPath 结果。 + } - void applyToGraphic(Canvas* canvas, RenderCache* cache, - std::shared_ptr graphic) const override; + void applyToGraphic(Canvas* canvas, RenderCache* cache, + std::shared_ptr graphic) const override; - std::shared_ptr mergeWith(const Modifier* modifier) const override; + std::shared_ptr mergeWith(const Modifier* modifier) const override; - private: - Opacity alpha = Opaque; - Enum blendMode = BlendMode::Normal; +private: + Opacity alpha = Opaque; + Enum blendMode = BlendMode::Normal; }; class ClipModifier : public Modifier { - public: - explicit ClipModifier(Path clip) : clip(std::move(clip)) { - } +public: + explicit ClipModifier(Path clip) : clip(std::move(clip)) { + } - ID type() const override { - static const auto TypeID = UniqueID::Next(); - return TypeID; - } + ID type() const override { + static const auto TypeID = UniqueID::Next(); + return TypeID; + } - bool isEmpty() const override { - return clip.isEmpty(); - } + bool isEmpty() const override { + return clip.isEmpty(); + } - bool hitTest(RenderCache*, float x, float y) const override { - return clip.contains(x, y); - } + bool hitTest(RenderCache*, float x, float y) const override { + return clip.contains(x, y); + } - void prepare(RenderCache*) const override { - } + void prepare(RenderCache*) const override { + } - void applyToBounds(Rect* bounds) const override; + void applyToBounds(Rect* bounds) const override; - bool applyToPath(Path* path) const override; + bool applyToPath(Path* path) const override; - void applyToGraphic(Canvas* canvas, RenderCache* cache, - std::shared_ptr graphic) const override; + void applyToGraphic(Canvas* canvas, RenderCache* cache, + std::shared_ptr graphic) const override; - std::shared_ptr mergeWith(const Modifier* modifier) const override; + std::shared_ptr mergeWith(const Modifier* modifier) const override; - private: - Path clip = {}; +private: + Path clip = {}; }; class MaskModifier : public Modifier { - public: - MaskModifier(std::shared_ptr mask, bool inverted) - : mask(std::move(mask)), inverted(inverted) { - } +public: + MaskModifier(std::shared_ptr mask, bool inverted) + : mask(std::move(mask)), inverted(inverted) { + } - ID type() const override { - static const auto TypeID = UniqueID::Next(); - return TypeID; - } + ID type() const override { + static const auto TypeID = UniqueID::Next(); + return TypeID; + } - bool isEmpty() const override { - return mask == nullptr; - } + bool isEmpty() const override { + return mask == nullptr; + } - bool hitTest(RenderCache* cache, float x, float y) const override; + bool hitTest(RenderCache* cache, float x, float y) const override; - void prepare(RenderCache* cache) const override; + void prepare(RenderCache* cache) const override; - void applyToBounds(Rect* bounds) const override; + void applyToBounds(Rect* bounds) const override; - bool applyToPath(Path*) const override { - return false; - } + bool applyToPath(Path*) const override { + return false; + } - void applyToGraphic(Canvas* canvas, RenderCache* cache, - std::shared_ptr graphic) const override; + void applyToGraphic(Canvas* canvas, RenderCache* cache, + std::shared_ptr graphic) const override; - std::shared_ptr mergeWith(const Modifier*) const override { - return nullptr; - } + std::shared_ptr mergeWith(const Modifier*) const override { + return nullptr; + } - private: - // 可能是 nullptr - std::shared_ptr mask = nullptr; - bool inverted = false; +private: + // 可能是 nullptr + std::shared_ptr mask = nullptr; + bool inverted = false; }; //================================================================================ std::shared_ptr Modifier::MakeBlend(Opacity alpha, Enum blendMode) { - if (alpha == Opaque && blendMode == BlendMode::Normal) { - return nullptr; - } - return std::make_shared(alpha, blendMode); + if (alpha == Opaque && blendMode == BlendMode::Normal) { + return nullptr; + } + return std::make_shared(alpha, blendMode); } std::shared_ptr Modifier::MakeClip(const Path& clip) { - if (clip.isEmpty() && clip.isInverseFillType()) { - // is full. - return nullptr; - } - return std::make_shared(clip); + if (clip.isEmpty() && clip.isInverseFillType()) { + // is full. + return nullptr; + } + return std::make_shared(clip); } std::shared_ptr Modifier::MakeMask(std::shared_ptr graphic, bool inverted) { - if (graphic == nullptr && inverted) { - // 返回空,表示保留目标对象的全部内容。 - return nullptr; - } - Path clipPath = {}; - if (graphic && graphic->getPath(&clipPath)) { - if (inverted) { - clipPath.toggleInverseFillType(); + if (graphic == nullptr && inverted) { + // 返回空,表示保留目标对象的全部内容。 + return nullptr; + } + Path clipPath = {}; + if (graphic && graphic->getPath(&clipPath)) { + if (inverted) { + clipPath.toggleInverseFillType(); + } + return Modifier::MakeClip(clipPath); } - return Modifier::MakeClip(clipPath); - } - return std::make_shared(graphic, inverted); + return std::make_shared(graphic, inverted); } //================================================================================ bool BlendModifier::hitTest(RenderCache*, float, float) const { - return alpha != Transparent; + return alpha != Transparent; } void BlendModifier::applyToGraphic(Canvas* canvas, RenderCache* cache, std::shared_ptr graphic) const { - canvas->save(); - canvas->concatAlpha(alpha); - canvas->concatBlendMode(ToBlend(blendMode)); - graphic->draw(canvas, cache); - canvas->restore(); + canvas->save(); + canvas->concatAlpha(alpha); + canvas->concatBlendMode(ToBlend(blendMode)); + graphic->draw(canvas, cache); + canvas->restore(); } std::shared_ptr BlendModifier::mergeWith(const Modifier* modifier) const { - auto target = static_cast(modifier); - if (target->blendMode != BlendMode::Normal && blendMode != BlendMode::Normal) { - return nullptr; - } - auto newBlendMode = blendMode != BlendMode::Normal ? blendMode : target->blendMode; - auto newAlpha = OpacityConcat(alpha, target->alpha); - return std::make_shared(newAlpha, newBlendMode); + auto target = static_cast(modifier); + if (target->blendMode != BlendMode::Normal && blendMode != BlendMode::Normal) { + return nullptr; + } + auto newBlendMode = blendMode != BlendMode::Normal ? blendMode : target->blendMode; + auto newAlpha = OpacityConcat(alpha, target->alpha); + return std::make_shared(newAlpha, newBlendMode); } void ClipModifier::applyToBounds(Rect* bounds) const { - Path boundsPath = {}; - boundsPath.addRect(*bounds); - boundsPath.addPath(clip, PathOp::Intersect); - *bounds = boundsPath.getBounds(); + Path boundsPath = {}; + boundsPath.addRect(*bounds); + boundsPath.addPath(clip, PathOp::Intersect); + *bounds = boundsPath.getBounds(); } bool ClipModifier::applyToPath(Path* path) const { - path->addPath(clip, PathOp::Intersect); - return true; + path->addPath(clip, PathOp::Intersect); + return true; } void ClipModifier::applyToGraphic(Canvas* canvas, RenderCache* cache, std::shared_ptr graphic) const { - canvas->save(); - canvas->clipPath(clip); - graphic->draw(canvas, cache); - canvas->restore(); + canvas->save(); + canvas->clipPath(clip); + graphic->draw(canvas, cache); + canvas->restore(); } std::shared_ptr ClipModifier::mergeWith(const Modifier* modifier) const { - auto target = static_cast(modifier); - auto newClip = clip; - newClip.addPath(target->clip, PathOp::Intersect); - return std::make_shared(newClip); + auto target = static_cast(modifier); + auto newClip = clip; + newClip.addPath(target->clip, PathOp::Intersect); + return std::make_shared(newClip); } bool MaskModifier::hitTest(RenderCache* cache, float x, float y) const { - if (mask == nullptr) { - return false; - } - auto result = mask->hitTest(cache, x, y); - return result != inverted; + if (mask == nullptr) { + return false; + } + auto result = mask->hitTest(cache, x, y); + return result != inverted; } void MaskModifier::prepare(RenderCache* cache) const { - if (mask) { - mask->prepare(cache); - } + if (mask) { + mask->prepare(cache); + } } void MaskModifier::applyToBounds(Rect* bounds) const { - if (mask == nullptr) { - bounds->setEmpty(); - return; - } - if (!inverted) { - Rect clipBounds = Rect::MakeEmpty(); - mask->measureBounds(&clipBounds); - if (!bounds->intersect(clipBounds)) { - bounds->setEmpty(); + if (mask == nullptr) { + bounds->setEmpty(); + return; + } + if (!inverted) { + Rect clipBounds = Rect::MakeEmpty(); + mask->measureBounds(&clipBounds); + if (!bounds->intersect(clipBounds)) { + bounds->setEmpty(); + } } - } } void MaskModifier::applyToGraphic(Canvas* canvas, RenderCache* cache, std::shared_ptr graphic) const { - if (mask == nullptr) { - return; - } - Rect bounds = Rect::MakeEmpty(); - graphic->measureBounds(&bounds); - applyToBounds(&bounds); - if (bounds.isEmpty()) { - // 与遮罩不相交,直接跳过绘制。 - return; - } - auto contentSurface = canvas->makeContentSurface(bounds, FLT_MAX); - if (contentSurface == nullptr) { - return; - } - auto contentCanvas = contentSurface->getCanvas(); - auto contentMatrix = contentCanvas->getMatrix(); - graphic->draw(contentCanvas, cache); - auto maskSurface = Surface::Make(contentSurface->getContext(), contentSurface->width(), - contentSurface->height(), true); - if (maskSurface == nullptr) { - maskSurface = Surface::Make(contentSurface->getContext(), contentSurface->width(), - contentSurface->height()); - } - if (maskSurface == nullptr) { - return; - } - auto maskCanvas = maskSurface->getCanvas(); - maskCanvas->setMatrix(contentMatrix); - mask->draw(maskCanvas, cache); - auto maskTexture = maskSurface->getTexture(); - auto texture = contentSurface->getTexture(); - auto scaleFactor = GetMaxScaleFactor(contentMatrix); - auto matrix = Matrix::MakeScale(1.0f / scaleFactor); - matrix.postTranslate(bounds.x(), bounds.y()); - canvas->save(); - canvas->concat(matrix); - canvas->drawTexture(texture.get(), maskTexture.get(), inverted); - canvas->restore(); + if (mask == nullptr) { + return; + } + Rect bounds = Rect::MakeEmpty(); + graphic->measureBounds(&bounds); + applyToBounds(&bounds); + if (bounds.isEmpty()) { + // 与遮罩不相交,直接跳过绘制。 + return; + } + auto contentSurface = canvas->makeContentSurface(bounds, FLT_MAX); + if (contentSurface == nullptr) { + return; + } + auto contentCanvas = contentSurface->getCanvas(); + auto contentMatrix = contentCanvas->getMatrix(); + graphic->draw(contentCanvas, cache); + auto maskSurface = Surface::Make(contentSurface->getContext(), contentSurface->width(), + contentSurface->height(), true); + if (maskSurface == nullptr) { + maskSurface = Surface::Make(contentSurface->getContext(), contentSurface->width(), + contentSurface->height()); + } + if (maskSurface == nullptr) { + return; + } + auto maskCanvas = maskSurface->getCanvas(); + maskCanvas->setMatrix(contentMatrix); + mask->draw(maskCanvas, cache); + auto maskTexture = maskSurface->getTexture(); + auto texture = contentSurface->getTexture(); + auto scaleFactor = GetMaxScaleFactor(contentMatrix); + auto matrix = Matrix::MakeScale(1.0f / scaleFactor); + matrix.postTranslate(bounds.x(), bounds.y()); + canvas->save(); + canvas->concat(matrix); + canvas->drawTexture(texture.get(), maskTexture.get(), inverted); + canvas->restore(); } } // namespace pag diff --git a/src/rendering/graphics/Modifier.h b/src/rendering/graphics/Modifier.h index f48f1663c0..60197a8115 100644 --- a/src/rendering/graphics/Modifier.h +++ b/src/rendering/graphics/Modifier.h @@ -28,55 +28,55 @@ class Canvas; class RenderCache; class Modifier { - public: - static std::shared_ptr MakeBlend(Opacity alpha, Enum blendMode); - static std::shared_ptr MakeClip(const Path& clip); - static std::shared_ptr MakeMask(std::shared_ptr graphic, bool inverted); +public: + static std::shared_ptr MakeBlend(Opacity alpha, Enum blendMode); + static std::shared_ptr MakeClip(const Path& clip); + static std::shared_ptr MakeMask(std::shared_ptr graphic, bool inverted); - virtual ~Modifier() = default; + virtual ~Modifier() = default; - /** - * Returns true if the result of applying this modifier is empty. - */ - virtual bool isEmpty() const = 0; + /** + * Returns true if the result of applying this modifier is empty. + */ + virtual bool isEmpty() const = 0; - /** - * Returns the type ID of this modifier. - */ - virtual ID type() const = 0; + /** + * Returns the type ID of this modifier. + */ + virtual ID type() const = 0; - /** - * Return false if target content with modification applied does not overlap or intersect with - * specified point. - */ - virtual bool hitTest(RenderCache* cache, float x, float y) const = 0; + /** + * Return false if target content with modification applied does not overlap or intersect with + * specified point. + */ + virtual bool hitTest(RenderCache* cache, float x, float y) const = 0; - /** - * Prepares this modifier for next applyToGraphic() call. It collects all CPU tasks in this - * modifier and run them in parallel immediately. - */ - virtual void prepare(RenderCache* cache) const = 0; + /** + * Prepares this modifier for next applyToGraphic() call. It collects all CPU tasks in this + * modifier and run them in parallel immediately. + */ + virtual void prepare(RenderCache* cache) const = 0; - /** - * Applies the modification to content bounds. - */ - virtual void applyToBounds(Rect* bounds) const = 0; + /** + * Applies the modification to content bounds. + */ + virtual void applyToBounds(Rect* bounds) const = 0; - /** - * Returns false if this modifier can not process path. - */ - virtual bool applyToPath(Path* path) const = 0; + /** + * Returns false if this modifier can not process path. + */ + virtual bool applyToPath(Path* path) const = 0; - /** - * Draws the graphic to specified canvas with custom modification. - */ - virtual void applyToGraphic(Canvas* canvas, RenderCache* cache, - std::shared_ptr graphic) const = 0; + /** + * Draws the graphic to specified canvas with custom modification. + */ + virtual void applyToGraphic(Canvas* canvas, RenderCache* cache, + std::shared_ptr graphic) const = 0; - /** - * Returns a new modifier which is the combination of this modifier and specified modifier if this - * modifier can be merged with specified modifier. - */ - virtual std::shared_ptr mergeWith(const Modifier* modifier) const = 0; + /** + * Returns a new modifier which is the combination of this modifier and specified modifier if this + * modifier can be merged with specified modifier. + */ + virtual std::shared_ptr mergeWith(const Modifier* modifier) const = 0; }; } // namespace pag diff --git a/src/rendering/graphics/Picture.cpp b/src/rendering/graphics/Picture.cpp index 0cd0f273c9..d25c915985 100644 --- a/src/rendering/graphics/Picture.cpp +++ b/src/rendering/graphics/Picture.cpp @@ -26,433 +26,433 @@ namespace pag { // 若当前直接绘制纹理性能是最好的,就直接绘制,否则返回 false。 static bool TryDrawDirectly(Canvas* canvas, const Texture* texture, const RGBAAALayout* layout) { - if (texture == nullptr) { + if (texture == nullptr) { + return false; + } + if (!texture->isYUV() && layout == nullptr) { + // RGBA 纹理始终可以直接上屏。 + canvas->drawTexture(texture); + // 防止临时纹理析构 + canvas->flush(); + return true; + } + auto totalMatrix = canvas->getMatrix(); + auto scaleFactor = GetMaxScaleFactor(totalMatrix); + if (scaleFactor <= 1.0f) { + auto width = layout ? layout->width : texture->width(); + auto height = layout ? layout->height : texture->height(); + // 纹理格式为 YUV 或含有 RGBAAALayout 时在缩放值小于等于 1.0f 时才直接上屏会有更好的性能。 + auto bounds = Rect::MakeWH(static_cast(width), static_cast(height)); + auto result = canvas->hasComplexPaint(bounds); + if (!(result & PaintKind::Blend || result & PaintKind::Clip)) { + canvas->drawTexture(texture, layout); + // 防止临时纹理析构 + canvas->flush(); + return true; + } + } return false; - } - if (!texture->isYUV() && layout == nullptr) { - // RGBA 纹理始终可以直接上屏。 - canvas->drawTexture(texture); - // 防止临时纹理析构 - canvas->flush(); - return true; - } - auto totalMatrix = canvas->getMatrix(); - auto scaleFactor = GetMaxScaleFactor(totalMatrix); - if (scaleFactor <= 1.0f) { - auto width = layout ? layout->width : texture->width(); - auto height = layout ? layout->height : texture->height(); - // 纹理格式为 YUV 或含有 RGBAAALayout 时在缩放值小于等于 1.0f 时才直接上屏会有更好的性能。 - auto bounds = Rect::MakeWH(static_cast(width), static_cast(height)); - auto result = canvas->hasComplexPaint(bounds); - if (!(result & PaintKind::Blend || result & PaintKind::Clip)) { - canvas->drawTexture(texture, layout); - // 防止临时纹理析构 - canvas->flush(); - return true; - } - } - return false; } // 强制直接绘制纹理到 canvas。 static void DrawDirectly(Canvas* canvas, const Texture* texture, const RGBAAALayout* layout) { - if (texture == nullptr || TryDrawDirectly(canvas, texture, layout)) { - return; - } - auto width = layout ? layout->width : texture->width(); - auto height = layout ? layout->height : texture->height(); - auto surface = Surface::Make(canvas->getContext(), width, height); - if (surface == nullptr) { - return; - } - auto newCanvas = surface->getCanvas(); - newCanvas->drawTexture(texture, layout); - canvas->drawTexture(surface->getTexture().get()); - // 防止临时纹理析构 - canvas->flush(); + if (texture == nullptr || TryDrawDirectly(canvas, texture, layout)) { + return; + } + auto width = layout ? layout->width : texture->width(); + auto height = layout ? layout->height : texture->height(); + auto surface = Surface::Make(canvas->getContext(), width, height); + if (surface == nullptr) { + return; + } + auto newCanvas = surface->getCanvas(); + newCanvas->drawTexture(texture, layout); + canvas->drawTexture(surface->getTexture().get()); + // 防止临时纹理析构 + canvas->flush(); } static std::shared_ptr RescaleTexture(Context* context, Texture* texture, - float scaleFactor) { - if (texture == nullptr || scaleFactor == 0) { - return nullptr; - } - auto width = static_cast(ceilf(texture->width() * scaleFactor)); - auto height = static_cast(ceilf(texture->height() * scaleFactor)); - auto surface = Surface::Make(context, width, height); - if (surface == nullptr) { - return nullptr; - } - auto canvas = surface->getCanvas(); - canvas->setMatrix(Matrix::MakeScale(scaleFactor)); - canvas->drawTexture(texture); - return surface->getTexture(); + float scaleFactor) { + if (texture == nullptr || scaleFactor == 0) { + return nullptr; + } + auto width = static_cast(ceilf(texture->width() * scaleFactor)); + auto height = static_cast(ceilf(texture->height() * scaleFactor)); + auto surface = Surface::Make(context, width, height); + if (surface == nullptr) { + return nullptr; + } + auto canvas = surface->getCanvas(); + canvas->setMatrix(Matrix::MakeScale(scaleFactor)); + canvas->drawTexture(texture); + return surface->getTexture(); } //================================= TextureProxySnapshotPicture ==================================== class TextureProxyPicture : public Picture { - public: - TextureProxyPicture(ID assetID, TextureProxy* proxy, bool externalMemory) - : Picture(assetID), proxy(proxy), externalMemory(externalMemory) { - } - - ~TextureProxyPicture() override { - delete proxy; - } - - void measureBounds(Rect* bounds) const override { - bounds->setWH(static_cast(proxy->width()), static_cast(proxy->height())); - } - - bool hitTest(RenderCache* cache, float x, float y) override { - // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 - auto snapshot = cache->getSnapshot(assetID); - if (snapshot) { - return snapshot->hitTest(cache, x, y); - } - auto texture = proxy->getTexture(cache); - if (texture == nullptr) { - return false; +public: + TextureProxyPicture(ID assetID, TextureProxy* proxy, bool externalMemory) + : Picture(assetID), proxy(proxy), externalMemory(externalMemory) { } - auto surface = Surface::Make(cache->getContext(), 1, 1); - if (surface == nullptr) { - return false; + + ~TextureProxyPicture() override { + delete proxy; } - auto canvas = surface->getCanvas(); - canvas->setMatrix(Matrix::MakeTrans(-x, -y)); - canvas->drawTexture(texture.get()); - return surface->hitTest(0, 0); - } - bool getPath(Path*) const override { - return false; - } - - void prepare(RenderCache* cache) const override { - proxy->prepare(cache); - } - - void draw(Canvas* canvas, RenderCache* cache) const override { - auto oldMatrix = canvas->getMatrix(); - canvas->concat(extraMatrix); - if (proxy->cacheEnabled()) { - auto texture = proxy->getTexture(cache); - if (TryDrawDirectly(canvas, texture.get(), nullptr)) { - canvas->setMatrix(oldMatrix); - return; - } + void measureBounds(Rect* bounds) const override { + bounds->setWH(static_cast(proxy->width()), static_cast(proxy->height())); } - auto snapshot = cache->getSnapshot(this); - if (snapshot) { - canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); - } else { - auto texture = proxy->getTexture(cache); - DrawDirectly(canvas, texture.get(), nullptr); + + bool hitTest(RenderCache* cache, float x, float y) override { + // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 + auto snapshot = cache->getSnapshot(assetID); + if (snapshot) { + return snapshot->hitTest(cache, x, y); + } + auto texture = proxy->getTexture(cache); + if (texture == nullptr) { + return false; + } + auto surface = Surface::Make(cache->getContext(), 1, 1); + if (surface == nullptr) { + return false; + } + auto canvas = surface->getCanvas(); + canvas->setMatrix(Matrix::MakeTrans(-x, -y)); + canvas->drawTexture(texture.get()); + return surface->hitTest(0, 0); } - canvas->setMatrix(oldMatrix); - } - private: - TextureProxy* proxy = nullptr; - bool externalMemory = false; - Matrix extraMatrix = Matrix::I(); + bool getPath(Path*) const override { + return false; + } - float getScaleFactor(float maxScaleFactor) const override { - if (externalMemory) { - return 1.0f; + void prepare(RenderCache* cache) const override { + proxy->prepare(cache); } - // 图片缩放值不需要大于 1.0f,清晰度无法继续提高。 - return std::min(maxScaleFactor, 1.0f); - } - std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { - auto texture = proxy->getTexture(cache); - if (texture == nullptr) { - return nullptr; + void draw(Canvas* canvas, RenderCache* cache) const override { + auto oldMatrix = canvas->getMatrix(); + canvas->concat(extraMatrix); + if (proxy->cacheEnabled()) { + auto texture = proxy->getTexture(cache); + if (TryDrawDirectly(canvas, texture.get(), nullptr)) { + canvas->setMatrix(oldMatrix); + return; + } + } + auto snapshot = cache->getSnapshot(this); + if (snapshot) { + canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); + } else { + auto texture = proxy->getTexture(cache); + DrawDirectly(canvas, texture.get(), nullptr); + } + canvas->setMatrix(oldMatrix); } - if (scaleFactor != 1.0f || texture->isYUV()) { - texture = RescaleTexture(cache->getContext(), texture.get(), scaleFactor); + +private: + TextureProxy* proxy = nullptr; + bool externalMemory = false; + Matrix extraMatrix = Matrix::I(); + + float getScaleFactor(float maxScaleFactor) const override { + if (externalMemory) { + return 1.0f; + } + // 图片缩放值不需要大于 1.0f,清晰度无法继续提高。 + return std::min(maxScaleFactor, 1.0f); } - if (texture == nullptr) { - return nullptr; + + std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { + auto texture = proxy->getTexture(cache); + if (texture == nullptr) { + return nullptr; + } + if (scaleFactor != 1.0f || texture->isYUV()) { + texture = RescaleTexture(cache->getContext(), texture.get(), scaleFactor); + } + if (texture == nullptr) { + return nullptr; + } + auto snapshot = new Snapshot(texture, Matrix::MakeScale(1 / scaleFactor)); + return std::unique_ptr(snapshot); } - auto snapshot = new Snapshot(texture, Matrix::MakeScale(1 / scaleFactor)); - return std::unique_ptr(snapshot); - } - friend class Picture; + friend class Picture; }; //=================================== TextureProxyPicture ========================================== //===================================== RGBAAAPicture ============================================== class RGBAAAPicture : public Picture { - public: - RGBAAAPicture(ID assetID, TextureProxy* proxy, const RGBAAALayout& layout) - : Picture(assetID), proxy(proxy), layout(layout) { - } - - ~RGBAAAPicture() override { - delete proxy; - } - - void measureBounds(Rect* bounds) const override { - bounds->setWH(static_cast(layout.width), static_cast(layout.height)); - } - - bool hitTest(RenderCache* cache, float x, float y) override { - // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 - auto snapshot = cache->getSnapshot(assetID); - if (snapshot) { - return snapshot->hitTest(cache, x, y); - } - auto texture = proxy->getTexture(cache); - auto surface = Surface::Make(cache->getContext(), 1, 1); - if (surface == nullptr) { - return false; +public: + RGBAAAPicture(ID assetID, TextureProxy* proxy, const RGBAAALayout& layout) + : Picture(assetID), proxy(proxy), layout(layout) { } - auto canvas = surface->getCanvas(); - auto matrix = Matrix::MakeTrans(static_cast(-x), static_cast(-y)); - canvas->setMatrix(matrix); - canvas->drawTexture(texture.get(), &layout); - return surface->hitTest(0, 0); - } - bool getPath(Path*) const override { - return false; - } - - void prepare(RenderCache* cache) const override { - proxy->prepare(cache); - } - - void draw(Canvas* canvas, RenderCache* cache) const override { - if (proxy->cacheEnabled()) { - // proxy在纯静态视频序列帧中不会缓存解码器 - // 如果将texture获取放在snapshot获取之前,会导致每帧都创建解码器 - auto texture = proxy->getTexture(cache); - if (TryDrawDirectly(canvas, texture.get(), &layout)) { - return; - } + ~RGBAAAPicture() override { + delete proxy; } - // 因为视频绘制会涉及自定义的 OpenGL 操作。 - // 要先 flush 父级 SkCanvas 里当前的 OpenGL 操作,防止渲染异常。 - canvas->flush(); - auto snapshot = cache->getSnapshot(this); - if (snapshot) { - canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); - return; - } - auto texture = proxy->getTexture(cache); - DrawDirectly(canvas, texture.get(), &layout); - } - - private: - TextureProxy* proxy = nullptr; - RGBAAALayout layout = {}; - - float getScaleFactor(float maxScaleFactor) const override { - // 视频帧缩放值不需要大于 1.0f,清晰度无法继续提高。 - return std::min(maxScaleFactor, 1.0f); - } - - std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { - auto width = static_cast(ceilf(static_cast(layout.width) * scaleFactor)); - auto height = static_cast(ceilf(static_cast(layout.height) * scaleFactor)); - auto surface = Surface::Make(cache->getContext(), width, height); - if (surface == nullptr) { - return nullptr; + + void measureBounds(Rect* bounds) const override { + bounds->setWH(static_cast(layout.width), static_cast(layout.height)); + } + + bool hitTest(RenderCache* cache, float x, float y) override { + // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 + auto snapshot = cache->getSnapshot(assetID); + if (snapshot) { + return snapshot->hitTest(cache, x, y); + } + auto texture = proxy->getTexture(cache); + auto surface = Surface::Make(cache->getContext(), 1, 1); + if (surface == nullptr) { + return false; + } + auto canvas = surface->getCanvas(); + auto matrix = Matrix::MakeTrans(static_cast(-x), static_cast(-y)); + canvas->setMatrix(matrix); + canvas->drawTexture(texture.get(), &layout); + return surface->hitTest(0, 0); + } + + bool getPath(Path*) const override { + return false; + } + + void prepare(RenderCache* cache) const override { + proxy->prepare(cache); + } + + void draw(Canvas* canvas, RenderCache* cache) const override { + if (proxy->cacheEnabled()) { + // proxy在纯静态视频序列帧中不会缓存解码器 + // 如果将texture获取放在snapshot获取之前,会导致每帧都创建解码器 + auto texture = proxy->getTexture(cache); + if (TryDrawDirectly(canvas, texture.get(), &layout)) { + return; + } + } + // 因为视频绘制会涉及自定义的 OpenGL 操作。 + // 要先 flush 父级 SkCanvas 里当前的 OpenGL 操作,防止渲染异常。 + canvas->flush(); + auto snapshot = cache->getSnapshot(this); + if (snapshot) { + canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); + return; + } + auto texture = proxy->getTexture(cache); + DrawDirectly(canvas, texture.get(), &layout); + } + +private: + TextureProxy* proxy = nullptr; + RGBAAALayout layout = {}; + + float getScaleFactor(float maxScaleFactor) const override { + // 视频帧缩放值不需要大于 1.0f,清晰度无法继续提高。 + return std::min(maxScaleFactor, 1.0f); } - auto texture = proxy->getTexture(cache); - auto canvas = surface->getCanvas(); - canvas->setMatrix(Matrix::MakeScale(scaleFactor)); - canvas->drawTexture(texture.get(), &layout); - auto snapshot = new Snapshot(surface->getTexture(), Matrix::MakeScale(1 / scaleFactor)); - return std::unique_ptr(snapshot); - } - friend class Graphic; + std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { + auto width = static_cast(ceilf(static_cast(layout.width) * scaleFactor)); + auto height = static_cast(ceilf(static_cast(layout.height) * scaleFactor)); + auto surface = Surface::Make(cache->getContext(), width, height); + if (surface == nullptr) { + return nullptr; + } + auto texture = proxy->getTexture(cache); + auto canvas = surface->getCanvas(); + canvas->setMatrix(Matrix::MakeScale(scaleFactor)); + canvas->drawTexture(texture.get(), &layout); + auto snapshot = new Snapshot(surface->getTexture(), Matrix::MakeScale(1 / scaleFactor)); + return std::unique_ptr(snapshot); + } + + friend class Graphic; }; //====================================== RGBAAAPicture ============================================= //====================================== SnapshotPicture =========================================== class SnapshotPictureOptions : public SurfaceOptions { - public: - bool skipSnapshotPictureCache = false; +public: + bool skipSnapshotPictureCache = false; }; class SnapshotPicture : public Picture { - public: - SnapshotPicture(ID assetID, std::shared_ptr graphic) - : Picture(assetID), graphic(std::move(graphic)) { - } - - void measureBounds(Rect* bounds) const override { - graphic->measureBounds(bounds); - } - - bool hitTest(RenderCache* cache, float x, float y) override { - // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 - auto snapshot = cache->getSnapshot(assetID); - if (snapshot) { - return snapshot->hitTest(cache, x, y); - } - return graphic->hitTest(cache, x, y); - } - - bool getPath(Path* path) const override { - return graphic->getPath(path); - } - - void prepare(RenderCache* cache) const override { - graphic->prepare(cache); - } - - void draw(Canvas* canvas, RenderCache* cache) const override { - auto options = static_cast(canvas->surfaceOptions()); - if (options && options->skipSnapshotPictureCache) { - graphic->draw(canvas, cache); - return; - } - auto snapshot = cache->getSnapshot(this); - if (snapshot == nullptr) { - graphic->draw(canvas, cache); - return; - } - canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); - } - - protected: - float getScaleFactor(float maxScaleFactor) const override { - return maxScaleFactor; - } - - std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { - Rect bounds = Rect::MakeEmpty(); - graphic->measureBounds(&bounds); - auto width = static_cast(ceilf(bounds.width() * scaleFactor)); - auto height = static_cast(ceilf(bounds.height() * scaleFactor)); - auto surface = Surface::Make(cache->getContext(), width, height); - if (surface == nullptr) { - return nullptr; +public: + SnapshotPicture(ID assetID, std::shared_ptr graphic) + : Picture(assetID), graphic(std::move(graphic)) { } - auto options = std::make_unique(); - options->skipSnapshotPictureCache = true; - surface->setOptions(std::move(options)); - auto canvas = surface->getCanvas(); - auto matrix = Matrix::MakeScale(scaleFactor); - matrix.preTranslate(-bounds.x(), -bounds.y()); - canvas->setMatrix(matrix); - graphic->draw(canvas, cache); - auto drawingMatrix = Matrix::I(); - matrix.invert(&drawingMatrix); - auto snapshot = new Snapshot(surface->getTexture(), drawingMatrix); - return std::unique_ptr(snapshot); - } - - private: - std::shared_ptr graphic = nullptr; + + void measureBounds(Rect* bounds) const override { + graphic->measureBounds(bounds); + } + + bool hitTest(RenderCache* cache, float x, float y) override { + // 碰撞检测过程不允许生成新的GPU缓存,因为碰撞结束不会触发缓存清理操作,长时间不进入下一次绘制有可能导致显存泄露。 + auto snapshot = cache->getSnapshot(assetID); + if (snapshot) { + return snapshot->hitTest(cache, x, y); + } + return graphic->hitTest(cache, x, y); + } + + bool getPath(Path* path) const override { + return graphic->getPath(path); + } + + void prepare(RenderCache* cache) const override { + graphic->prepare(cache); + } + + void draw(Canvas* canvas, RenderCache* cache) const override { + auto options = static_cast(canvas->surfaceOptions()); + if (options && options->skipSnapshotPictureCache) { + graphic->draw(canvas, cache); + return; + } + auto snapshot = cache->getSnapshot(this); + if (snapshot == nullptr) { + graphic->draw(canvas, cache); + return; + } + canvas->drawTexture(snapshot->getTexture(), snapshot->getMatrix()); + } + +protected: + float getScaleFactor(float maxScaleFactor) const override { + return maxScaleFactor; + } + + std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const override { + Rect bounds = Rect::MakeEmpty(); + graphic->measureBounds(&bounds); + auto width = static_cast(ceilf(bounds.width() * scaleFactor)); + auto height = static_cast(ceilf(bounds.height() * scaleFactor)); + auto surface = Surface::Make(cache->getContext(), width, height); + if (surface == nullptr) { + return nullptr; + } + auto options = std::make_unique(); + options->skipSnapshotPictureCache = true; + surface->setOptions(std::move(options)); + auto canvas = surface->getCanvas(); + auto matrix = Matrix::MakeScale(scaleFactor); + matrix.preTranslate(-bounds.x(), -bounds.y()); + canvas->setMatrix(matrix); + graphic->draw(canvas, cache); + auto drawingMatrix = Matrix::I(); + matrix.invert(&drawingMatrix); + auto snapshot = new Snapshot(surface->getTexture(), drawingMatrix); + return std::unique_ptr(snapshot); + } + +private: + std::shared_ptr graphic = nullptr; }; //===================================== SnapshotPicture ============================================ //==================================== Texture Proxies ============================================= class BitmapTextureProxy : public TextureProxy { - public: - explicit BitmapTextureProxy(const Bitmap& bitmap) - : TextureProxy(bitmap.width(), bitmap.height()), bitmap(bitmap) { - } +public: + explicit BitmapTextureProxy(const Bitmap& bitmap) + : TextureProxy(bitmap.width(), bitmap.height()), bitmap(bitmap) { + } - bool cacheEnabled() const override { - return false; - } + bool cacheEnabled() const override { + return false; + } - void prepare(RenderCache*) const override { - } + void prepare(RenderCache*) const override { + } - std::shared_ptr getTexture(RenderCache* cache) const override { - auto startTime = GetTimer(); - auto texture = bitmap.makeTexture(cache->getContext()); - cache->recordTextureUploadingTime(GetTimer() - startTime); - return texture; - } + std::shared_ptr getTexture(RenderCache* cache) const override { + auto startTime = GetTimer(); + auto texture = bitmap.makeTexture(cache->getContext()); + cache->recordTextureUploadingTime(GetTimer() - startTime); + return texture; + } - private: - Bitmap bitmap = {}; +private: + Bitmap bitmap = {}; }; class ImageTextureProxy : public TextureProxy { - public: - explicit ImageTextureProxy(ID assetID, int width, int height, std::shared_ptr image) - : TextureProxy(width, height), assetID(assetID), image(std::move(image)) { - } +public: + explicit ImageTextureProxy(ID assetID, int width, int height, std::shared_ptr image) + : TextureProxy(width, height), assetID(assetID), image(std::move(image)) { + } - bool cacheEnabled() const override { - return false; - } - - void prepare(RenderCache* cache) const override { - cache->prepareImage(assetID, image); - } - - std::shared_ptr getTexture(RenderCache* cache) const override { - auto startTime = GetTimer(); - auto buffer = cache->getImageBuffer(assetID); - if (buffer == nullptr) { - buffer = image->makeBuffer(); - } - cache->recordImageDecodingTime(GetTimer() - startTime); - if (buffer == nullptr) { - return nullptr; - } - startTime = GetTimer(); - auto texture = buffer->makeTexture(cache->getContext()); - cache->recordTextureUploadingTime(GetTimer() - startTime); - return texture; - } - - private: - ID assetID = 0; - std::shared_ptr image = nullptr; + bool cacheEnabled() const override { + return false; + } + + void prepare(RenderCache* cache) const override { + cache->prepareImage(assetID, image); + } + + std::shared_ptr getTexture(RenderCache* cache) const override { + auto startTime = GetTimer(); + auto buffer = cache->getImageBuffer(assetID); + if (buffer == nullptr) { + buffer = image->makeBuffer(); + } + cache->recordImageDecodingTime(GetTimer() - startTime); + if (buffer == nullptr) { + return nullptr; + } + startTime = GetTimer(); + auto texture = buffer->makeTexture(cache->getContext()); + cache->recordTextureUploadingTime(GetTimer() - startTime); + return texture; + } + +private: + ID assetID = 0; + std::shared_ptr image = nullptr; }; class BackendTextureProxy : public TextureProxy { - public: - BackendTextureProxy(const BackendTexture& texture, ImageOrigin origin, void* sharedContext) - : TextureProxy(texture.width(), texture.height()), - backendTexture(texture), - origin(origin), - sharedContext(sharedContext) { - } - - bool cacheEnabled() const override { - return false; - } - - void prepare(RenderCache*) const override { - } - - std::shared_ptr getTexture(RenderCache* cache) const override { - auto context = cache->getContext(); - if (!checkContext(context)) { - return nullptr; - } - return Texture::MakeFrom(context, backendTexture, origin); - } - - private: - BackendTexture backendTexture = {}; - ImageOrigin origin = ImageOrigin::TopLeft; - void* sharedContext = nullptr; - - bool checkContext(Context* context) const { - auto glDevice = static_cast(context->getDevice()); - if (!glDevice->sharableWith(sharedContext)) { - LOGE( - "A Graphic which made from a texture can not be drawn on to a PAGSurface" - " if its GPU context is not share context to the PAGSurface."); - return false; - } - return true; - } +public: + BackendTextureProxy(const BackendTexture& texture, ImageOrigin origin, void* sharedContext) + : TextureProxy(texture.width(), texture.height()), + backendTexture(texture), + origin(origin), + sharedContext(sharedContext) { + } + + bool cacheEnabled() const override { + return false; + } + + void prepare(RenderCache*) const override { + } + + std::shared_ptr getTexture(RenderCache* cache) const override { + auto context = cache->getContext(); + if (!checkContext(context)) { + return nullptr; + } + return Texture::MakeFrom(context, backendTexture, origin); + } + +private: + BackendTexture backendTexture = {}; + ImageOrigin origin = ImageOrigin::TopLeft; + void* sharedContext = nullptr; + + bool checkContext(Context* context) const { + auto glDevice = static_cast(context->getDevice()); + if (!glDevice->sharableWith(sharedContext)) { + LOGE( + "A Graphic which made from a texture can not be drawn on to a PAGSurface" + " if its GPU context is not share context to the PAGSurface."); + return false; + } + return true; + } }; //==================================== Texture Proxies ============================================= @@ -462,65 +462,65 @@ Picture::Picture(ID assetID) : assetID(assetID), uniqueKey(IDCount++) { } std::shared_ptr Picture::MakeFrom(ID assetID, std::shared_ptr image) { - if (image == nullptr) { - return nullptr; - } - auto extraMatrix = OrientationToMatrix(image->orientation(), image->width(), image->height()); - auto bounds = Rect::MakeWH(image->width(), image->height()); - extraMatrix.mapRect(&bounds); - auto textureProxy = new ImageTextureProxy(assetID, static_cast(bounds.width()), - static_cast(bounds.height()), image); - auto picture = std::make_shared(assetID, textureProxy, false); - picture->extraMatrix = extraMatrix; - return picture; + if (image == nullptr) { + return nullptr; + } + auto extraMatrix = OrientationToMatrix(image->orientation(), image->width(), image->height()); + auto bounds = Rect::MakeWH(image->width(), image->height()); + extraMatrix.mapRect(&bounds); + auto textureProxy = new ImageTextureProxy(assetID, static_cast(bounds.width()), + static_cast(bounds.height()), image); + auto picture = std::make_shared(assetID, textureProxy, false); + picture->extraMatrix = extraMatrix; + return picture; } std::shared_ptr Picture::MakeFrom(ID assetID, const Bitmap& bitmap) { - if (bitmap.isEmpty()) { - return nullptr; - } - auto proxy = new BitmapTextureProxy(bitmap); - return std::shared_ptr( - new TextureProxyPicture(assetID, proxy, bitmap.isHardwareBacked())); + if (bitmap.isEmpty()) { + return nullptr; + } + auto proxy = new BitmapTextureProxy(bitmap); + return std::shared_ptr( + new TextureProxyPicture(assetID, proxy, bitmap.isHardwareBacked())); } std::shared_ptr Picture::MakeFrom(ID assetID, const BackendTexture& texture, - ImageOrigin origin) { - if (!texture.isValid()) { - return nullptr; - } - auto context = NativeGLDevice::GetCurrentNativeHandle(); - if (context == nullptr) { - return nullptr; - } - auto proxy = new BackendTextureProxy(texture, origin, context); - return std::shared_ptr(new TextureProxyPicture(assetID, proxy, true)); + ImageOrigin origin) { + if (!texture.isValid()) { + return nullptr; + } + auto context = NativeGLDevice::GetCurrentNativeHandle(); + if (context == nullptr) { + return nullptr; + } + auto proxy = new BackendTextureProxy(texture, origin, context); + return std::shared_ptr(new TextureProxyPicture(assetID, proxy, true)); } std::shared_ptr Picture::MakeFrom(ID assetID, std::unique_ptr proxy) { - if (proxy == nullptr) { - return nullptr; - } - return std::shared_ptr(new TextureProxyPicture(assetID, proxy.release(), true)); + if (proxy == nullptr) { + return nullptr; + } + return std::shared_ptr(new TextureProxyPicture(assetID, proxy.release(), true)); } std::shared_ptr Picture::MakeFrom(ID assetID, std::unique_ptr proxy, - const RGBAAALayout& layout) { - if (layout.alphaStartX == 0 && layout.alphaStartY == 0) { - return Picture::MakeFrom(assetID, std::move(proxy)); - } - if (proxy == nullptr || layout.alphaStartX + layout.width > proxy->width() || - layout.alphaStartY + layout.height > proxy->height()) { - return nullptr; - } - return std::shared_ptr(new RGBAAAPicture(assetID, proxy.release(), layout)); + const RGBAAALayout& layout) { + if (layout.alphaStartX == 0 && layout.alphaStartY == 0) { + return Picture::MakeFrom(assetID, std::move(proxy)); + } + if (proxy == nullptr || layout.alphaStartX + layout.width > proxy->width() || + layout.alphaStartY + layout.height > proxy->height()) { + return nullptr; + } + return std::shared_ptr(new RGBAAAPicture(assetID, proxy.release(), layout)); } std::shared_ptr Picture::MakeFrom(ID assetID, std::shared_ptr graphic) { - if (assetID == 0 || graphic == nullptr || graphic->type() == GraphicType::Picture) { - return graphic; - } - return std::make_shared(assetID, graphic); + if (assetID == 0 || graphic == nullptr || graphic->type() == GraphicType::Picture) { + return graphic; + } + return std::make_shared(assetID, graphic); } } // namespace pag diff --git a/src/rendering/graphics/Picture.h b/src/rendering/graphics/Picture.h index 215c1742aa..69d73f64c8 100644 --- a/src/rendering/graphics/Picture.h +++ b/src/rendering/graphics/Picture.h @@ -32,57 +32,57 @@ namespace pag { * always greater than zero. Creating an Picture with zero width or height returns nullptr. */ class Picture : public Graphic { - public: - /** - * Creates a new Picture with specified Image. Return null if the proxy is null. - */ - static std::shared_ptr MakeFrom(ID assetID, std::shared_ptr image); +public: + /** + * Creates a new Picture with specified Image. Return null if the proxy is null. + */ + static std::shared_ptr MakeFrom(ID assetID, std::shared_ptr image); - /** - * Creates a new Picture with specified bitmap. Returns null if the bitmap is empty. - */ - static std::shared_ptr MakeFrom(ID assetID, const Bitmap& bitmap); + /** + * Creates a new Picture with specified bitmap. Returns null if the bitmap is empty. + */ + static std::shared_ptr MakeFrom(ID assetID, const Bitmap& bitmap); - /** - * Creates a new Picture with specified backend texture. Returns null if the texture is invalid. - */ - static std::shared_ptr MakeFrom(ID assetID, const BackendTexture& texture, - ImageOrigin origin); + /** + * Creates a new Picture with specified backend texture. Returns null if the texture is invalid. + */ + static std::shared_ptr MakeFrom(ID assetID, const BackendTexture& texture, + ImageOrigin origin); - /* - * Creates a new image with specified TextureProxy. Returns nullptr if the proxy is null. - */ - static std::shared_ptr MakeFrom(ID assetID, std::unique_ptr proxy); + /* + * Creates a new image with specified TextureProxy. Returns nullptr if the proxy is null. + */ + static std::shared_ptr MakeFrom(ID assetID, std::unique_ptr proxy); - /** - * Creates a new image with specified TextureProxy and RGBAAA layout. Returns null if the - * proxy is null or the layout is invalid. - */ - static std::shared_ptr MakeFrom(ID assetID, std::unique_ptr proxy, - const RGBAAALayout& layout); + /** + * Creates a new image with specified TextureProxy and RGBAAA layout. Returns null if the + * proxy is null or the layout is invalid. + */ + static std::shared_ptr MakeFrom(ID assetID, std::unique_ptr proxy, + const RGBAAALayout& layout); - /** - * Creates a new Picture with specified graphic. If the assetID is valid (not 0), the returned - * Picture may be cached as an internal texture representation during rendering, which increases - * performance for drawing complex content. - */ - static std::shared_ptr MakeFrom(ID assetID, std::shared_ptr graphic); + /** + * Creates a new Picture with specified graphic. If the assetID is valid (not 0), the returned + * Picture may be cached as an internal texture representation during rendering, which increases + * performance for drawing complex content. + */ + static std::shared_ptr MakeFrom(ID assetID, std::shared_ptr graphic); - explicit Picture(ID assetID); + explicit Picture(ID assetID); - GraphicType type() const final { - return GraphicType::Picture; - } + GraphicType type() const final { + return GraphicType::Picture; + } - protected: - ID assetID = 0; +protected: + ID assetID = 0; - virtual float getScaleFactor(float maxScaleFactor) const = 0; - virtual std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const = 0; + virtual float getScaleFactor(float maxScaleFactor) const = 0; + virtual std::unique_ptr makeSnapshot(RenderCache* cache, float scaleFactor) const = 0; - private: - uint64_t uniqueKey = 0; +private: + uint64_t uniqueKey = 0; - friend class RenderCache; + friend class RenderCache; }; } // namespace pag diff --git a/src/rendering/graphics/Recorder.cpp b/src/rendering/graphics/Recorder.cpp index 376cb64793..82a84c7160 100644 --- a/src/rendering/graphics/Recorder.cpp +++ b/src/rendering/graphics/Recorder.cpp @@ -22,146 +22,146 @@ namespace pag { enum class RecordType { Matrix, Layer }; class Record { - public: - explicit Record(const Matrix& matrix) : matrix(matrix) { - } +public: + explicit Record(const Matrix& matrix) : matrix(matrix) { + } - virtual ~Record() = default; + virtual ~Record() = default; - virtual RecordType type() const { - return RecordType::Matrix; - } + virtual RecordType type() const { + return RecordType::Matrix; + } - Matrix matrix = {}; + Matrix matrix = {}; }; class LayerRecord : public Record { - public: - LayerRecord(const Matrix& matrix, std::shared_ptr modifier, - std::vector> contents) - : Record(matrix), modifier(std::move(modifier)), oldNodes(std::move(contents)) { - } - - RecordType type() const override { - return RecordType::Layer; - } - - std::shared_ptr modifier = nullptr; - std::vector> oldNodes = {}; +public: + LayerRecord(const Matrix& matrix, std::shared_ptr modifier, + std::vector> contents) + : Record(matrix), modifier(std::move(modifier)), oldNodes(std::move(contents)) { + } + + RecordType type() const override { + return RecordType::Layer; + } + + std::shared_ptr modifier = nullptr; + std::vector> oldNodes = {}; }; Matrix Recorder::getMatrix() const { - Matrix totalMatrix = matrix; - for (int i = static_cast(records.size() - 1); i >= 0; i--) { - auto& record = records[i]; - if (record->type() == RecordType::Layer) { - totalMatrix.postConcat(record->matrix); + Matrix totalMatrix = matrix; + for (int i = static_cast(records.size() - 1); i >= 0; i--) { + auto& record = records[i]; + if (record->type() == RecordType::Layer) { + totalMatrix.postConcat(record->matrix); + } } - } - return totalMatrix; + return totalMatrix; } void Recorder::setMatrix(const Matrix& m) { - matrix = m; - auto count = static_cast(records.size()); - if (count > 0) { - auto totalMatrix = Matrix::I(); - for (auto i = count - 1; i >= 0; i--) { - auto& record = records[i]; - if (record->type() == RecordType::Layer) { - totalMatrix.postConcat(record->matrix); - } - } - if (totalMatrix.invert(&totalMatrix)) { - matrix.postConcat(totalMatrix); + matrix = m; + auto count = static_cast(records.size()); + if (count > 0) { + auto totalMatrix = Matrix::I(); + for (auto i = count - 1; i >= 0; i--) { + auto& record = records[i]; + if (record->type() == RecordType::Layer) { + totalMatrix.postConcat(record->matrix); + } + } + if (totalMatrix.invert(&totalMatrix)) { + matrix.postConcat(totalMatrix); + } } - } } void Recorder::concat(const Matrix& m) { - matrix.preConcat(m); + matrix.preConcat(m); } void Recorder::saveClip(float x, float y, float width, float height) { - Path path = {}; - path.addRect(Rect::MakeXYWH(x, y, width, height)); - saveClip(path); + Path path = {}; + path.addRect(Rect::MakeXYWH(x, y, width, height)); + saveClip(path); } void Recorder::saveClip(const Path& path) { - auto modifier = Modifier::MakeClip(path); - saveLayer(modifier); + auto modifier = Modifier::MakeClip(path); + saveLayer(modifier); } void Recorder::saveLayer(Opacity alpha, Enum blendMode) { - auto modifier = Modifier::MakeBlend(alpha, blendMode); - saveLayer(modifier); + auto modifier = Modifier::MakeBlend(alpha, blendMode); + saveLayer(modifier); } void Recorder::saveLayer(std::shared_ptr modifier) { - if (modifier == nullptr) { - save(); - return; - } - auto record = std::make_shared(matrix, modifier, layerContents); - records.push_back(record); - matrix = Matrix::I(); - layerContents = {}; - layerIndex++; + if (modifier == nullptr) { + save(); + return; + } + auto record = std::make_shared(matrix, modifier, layerContents); + records.push_back(record); + matrix = Matrix::I(); + layerContents = {}; + layerIndex++; } void Recorder::save() { - auto record = std::make_shared(matrix); - records.push_back(record); + auto record = std::make_shared(matrix); + records.push_back(record); } void Recorder::restore() { - if (records.empty()) { - return; - } - auto record = records.back(); - records.pop_back(); - matrix = record->matrix; - if (record->type() == RecordType::Layer) { - layerIndex--; - auto layerRecord = std::static_pointer_cast(record); - auto layerGraphic = Graphic::MakeCompose(layerContents); - layerGraphic = Graphic::MakeCompose(layerGraphic, layerRecord->modifier); - layerContents = layerRecord->oldNodes; - drawGraphic(layerGraphic); - } + if (records.empty()) { + return; + } + auto record = records.back(); + records.pop_back(); + matrix = record->matrix; + if (record->type() == RecordType::Layer) { + layerIndex--; + auto layerRecord = std::static_pointer_cast(record); + auto layerGraphic = Graphic::MakeCompose(layerContents); + layerGraphic = Graphic::MakeCompose(layerGraphic, layerRecord->modifier); + layerContents = layerRecord->oldNodes; + drawGraphic(layerGraphic); + } } size_t Recorder::getSaveCount() const { - return records.size(); + return records.size(); } void Recorder::restoreToCount(size_t saveCount) { - while (records.size() > saveCount) { - restore(); - } + while (records.size() > saveCount) { + restore(); + } } void Recorder::drawGraphic(std::shared_ptr graphic, const Matrix& m) { - auto oldMatrix = matrix; - matrix.preConcat(m); - drawGraphic(std::move(graphic)); - matrix = oldMatrix; + auto oldMatrix = matrix; + matrix.preConcat(m); + drawGraphic(std::move(graphic)); + matrix = oldMatrix; } void Recorder::drawGraphic(std::shared_ptr graphic) { - auto content = Graphic::MakeCompose(std::move(graphic), matrix); - if (content == nullptr) { - return; - } - if (layerIndex == 0) { - rootContents.push_back(content); - } else { - layerContents.push_back(content); - } + auto content = Graphic::MakeCompose(std::move(graphic), matrix); + if (content == nullptr) { + return; + } + if (layerIndex == 0) { + rootContents.push_back(content); + } else { + layerContents.push_back(content); + } } std::shared_ptr Recorder::makeGraphic() { - return Graphic::MakeCompose(rootContents); + return Graphic::MakeCompose(rootContents); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/graphics/Recorder.h b/src/rendering/graphics/Recorder.h index 1ef85a2529..8323b186e4 100644 --- a/src/rendering/graphics/Recorder.h +++ b/src/rendering/graphics/Recorder.h @@ -28,104 +28,104 @@ class Record; * new Graphic capturing the whole drawing commands which may be applied at a later time. */ class Recorder { - public: - /** - * Returns the current total matrix. - */ - Matrix getMatrix() const; - - /** - * Replaces transformation with specified matrix. Unlike concat(), any prior matrix state is - * overwritten. - * @param matrix matrix to copy, replacing existing Matrix - */ - void setMatrix(const Matrix& matrix); - - /** - * Replaces transformation with specified matrix premultiplied with existing Matrix. This has the - * effect of transforming the drawn geometry by matrix, before transforming the result with - * existing Matrix. - * @param matrix matrix to premultiply with existing Matrix - */ - void concat(const Matrix& matrix); - - /** - * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes - * to matrix, and blends layer with the clip rect onto prior layer. Saved Recorder state is put on - * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal - * number of calls to restore(). - */ - void saveClip(float x, float y, float width, float height); - - /** - * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes - * to matrix, and blends layer with the clip path onto prior layer. Saved Recorder state is put on - * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal - * number of calls to restore(). - */ - void saveClip(const Path& path); - - /** - * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes - * to matrix, and blends layer with specified styles onto prior layer. Saved Recorder state is put - * on a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal - * number of calls to restore(). - */ - void saveLayer(Opacity alpha, Enum blendMode); - - /** - * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes - * to matrix, and blends layer with the modifier onto prior layer. Saved Recorder state is put on - * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal - * number of calls to restore(). - */ - void saveLayer(std::shared_ptr modifier); - - /** - * Saves matrix. Calling restore() discards changes to them, restoring the matrix to its state - * when save() was called. Saved Recorder state is put on a stack, multiple calls to saveLayer(), - * saveClip() and save() should be balance by an equal number of calls to restore(). - */ - void save(); - - /** - * Removes changes to matrix and clips since Recorder state was last saved. The state is removed - * from the stack. Does nothing if the stack is empty. - */ - void restore(); - - /** - * Returns the number of saved states, the save count of a new recorder is 0. - */ - size_t getSaveCount() const; - - /** - * Restores state to specified saveCount. Does nothing if saveCount is greater than state stack - * count. Restores state to initial values if saveCount is equal to 0. - */ - void restoreToCount(size_t saveCount); - - /** - * Draws a graphic using current clip and matrix. - */ - void drawGraphic(std::shared_ptr graphic); - - /** - * Draws a graphic using current clip and extra matrix. - */ - void drawGraphic(std::shared_ptr graphic, const Matrix& matrix); - - /** - * Returns a Graphic capturing recorder contents. Subsequent drawing to recorder contents are not - * captured. Returns nullptr if the contents are empty. - */ - std::shared_ptr makeGraphic(); - - private: - std::vector> rootContents = {}; - int layerIndex = 0; - Matrix matrix = Matrix::I(); - std::vector> layerContents = {}; - std::vector> records = {}; +public: + /** + * Returns the current total matrix. + */ + Matrix getMatrix() const; + + /** + * Replaces transformation with specified matrix. Unlike concat(), any prior matrix state is + * overwritten. + * @param matrix matrix to copy, replacing existing Matrix + */ + void setMatrix(const Matrix& matrix); + + /** + * Replaces transformation with specified matrix premultiplied with existing Matrix. This has the + * effect of transforming the drawn geometry by matrix, before transforming the result with + * existing Matrix. + * @param matrix matrix to premultiply with existing Matrix + */ + void concat(const Matrix& matrix); + + /** + * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes + * to matrix, and blends layer with the clip rect onto prior layer. Saved Recorder state is put on + * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal + * number of calls to restore(). + */ + void saveClip(float x, float y, float width, float height); + + /** + * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes + * to matrix, and blends layer with the clip path onto prior layer. Saved Recorder state is put on + * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal + * number of calls to restore(). + */ + void saveClip(const Path& path); + + /** + * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes + * to matrix, and blends layer with specified styles onto prior layer. Saved Recorder state is put + * on a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal + * number of calls to restore(). + */ + void saveLayer(Opacity alpha, Enum blendMode); + + /** + * Saves matrix, and allocates a layer for subsequent drawing. Calling restore() discards changes + * to matrix, and blends layer with the modifier onto prior layer. Saved Recorder state is put on + * a stack, multiple calls to saveLayer(), saveClip() and save() should be balance by an equal + * number of calls to restore(). + */ + void saveLayer(std::shared_ptr modifier); + + /** + * Saves matrix. Calling restore() discards changes to them, restoring the matrix to its state + * when save() was called. Saved Recorder state is put on a stack, multiple calls to saveLayer(), + * saveClip() and save() should be balance by an equal number of calls to restore(). + */ + void save(); + + /** + * Removes changes to matrix and clips since Recorder state was last saved. The state is removed + * from the stack. Does nothing if the stack is empty. + */ + void restore(); + + /** + * Returns the number of saved states, the save count of a new recorder is 0. + */ + size_t getSaveCount() const; + + /** + * Restores state to specified saveCount. Does nothing if saveCount is greater than state stack + * count. Restores state to initial values if saveCount is equal to 0. + */ + void restoreToCount(size_t saveCount); + + /** + * Draws a graphic using current clip and matrix. + */ + void drawGraphic(std::shared_ptr graphic); + + /** + * Draws a graphic using current clip and extra matrix. + */ + void drawGraphic(std::shared_ptr graphic, const Matrix& matrix); + + /** + * Returns a Graphic capturing recorder contents. Subsequent drawing to recorder contents are not + * captured. Returns nullptr if the contents are empty. + */ + std::shared_ptr makeGraphic(); + +private: + std::vector> rootContents = {}; + int layerIndex = 0; + Matrix matrix = Matrix::I(); + std::vector> layerContents = {}; + std::vector> records = {}; }; } // namespace pag diff --git a/src/rendering/graphics/Shape.cpp b/src/rendering/graphics/Shape.cpp index 3eebe59735..afc5f683e8 100644 --- a/src/rendering/graphics/Shape.cpp +++ b/src/rendering/graphics/Shape.cpp @@ -22,58 +22,58 @@ namespace pag { std::shared_ptr Shape::MakeFrom(const Path& path, Color color) { - if (path.isEmpty()) { - return nullptr; - } - auto fill = new SolidFill(); - fill->color = color; - return std::shared_ptr(new Shape(path, fill)); + if (path.isEmpty()) { + return nullptr; + } + auto fill = new SolidFill(); + fill->color = color; + return std::shared_ptr(new Shape(path, fill)); } std::shared_ptr Shape::MakeFrom(const Path& path, const GradientPaint& gradient) { - if (path.isEmpty()) { - return nullptr; - } - auto fill = new GradientFill(); - fill->gradient = gradient; - return std::shared_ptr(new Shape(path, fill)); + if (path.isEmpty()) { + return nullptr; + } + auto fill = new GradientFill(); + fill->gradient = gradient; + return std::shared_ptr(new Shape(path, fill)); } Shape::Shape(Path path, ShapeFill* fill) : path(std::move(path)), fill(fill) { } Shape::~Shape() { - delete fill; + delete fill; } void Shape::measureBounds(Rect* bounds) const { - *bounds = path.getBounds(); + *bounds = path.getBounds(); } bool Shape::hitTest(RenderCache*, float x, float y) { - return path.contains(x, y); + return path.contains(x, y); } bool Shape::getPath(Path* result) const { - if (fill->type() == ShapeFillType::Gradient) { - return false; - } - result->addPath(path); - return true; + if (fill->type() == ShapeFillType::Gradient) { + return false; + } + result->addPath(path); + return true; } void Shape::prepare(RenderCache*) const { } void Shape::draw(Canvas* canvas, RenderCache*) const { - switch (fill->type()) { + switch (fill->type()) { case ShapeFillType::Solid: - canvas->drawPath(path, static_cast(fill)->color); - break; + canvas->drawPath(path, static_cast(fill)->color); + break; case ShapeFillType::Gradient: - canvas->drawPath(path, static_cast(fill)->gradient); - break; - } + canvas->drawPath(path, static_cast(fill)->gradient); + break; + } } } // namespace pag \ No newline at end of file diff --git a/src/rendering/graphics/Shape.h b/src/rendering/graphics/Shape.h index 6551b5af0a..69a357d2e9 100644 --- a/src/rendering/graphics/Shape.h +++ b/src/rendering/graphics/Shape.h @@ -24,58 +24,58 @@ namespace pag { enum class ShapeFillType { Solid, Gradient }; class ShapeFill { - public: - virtual ~ShapeFill() = default; +public: + virtual ~ShapeFill() = default; - virtual ShapeFillType type() const = 0; + virtual ShapeFillType type() const = 0; }; class SolidFill : public ShapeFill { - public: - ShapeFillType type() const override { - return ShapeFillType::Solid; - } +public: + ShapeFillType type() const override { + return ShapeFillType::Solid; + } - Color color; + Color color; }; class GradientFill : public ShapeFill { - public: - ShapeFillType type() const override { - return ShapeFillType::Gradient; - } +public: + ShapeFillType type() const override { + return ShapeFillType::Gradient; + } - GradientPaint gradient = {}; + GradientPaint gradient = {}; }; class Shape : public Graphic { - public: - /** - * Creates a shape Graphic with solid color fill. Returns nullptr if path is empty. - */ - static std::shared_ptr MakeFrom(const Path& path, Color color); - - /** - * Creates a shape Graphic with gradient color fill. Returns nullptr if path is empty. - */ - static std::shared_ptr MakeFrom(const Path& path, const GradientPaint& gradient); - - ~Shape() override; - - GraphicType type() const override { - return GraphicType::Shape; - } - - void measureBounds(Rect* bounds) const override; - bool hitTest(RenderCache* cache, float x, float y) override; - bool getPath(Path* result) const override; - void prepare(RenderCache* cache) const override; - void draw(Canvas* canvas, RenderCache* cache) const override; - - private: - Path path = {}; - ShapeFill* fill = nullptr; - - Shape(Path path, ShapeFill* fill); +public: + /** + * Creates a shape Graphic with solid color fill. Returns nullptr if path is empty. + */ + static std::shared_ptr MakeFrom(const Path& path, Color color); + + /** + * Creates a shape Graphic with gradient color fill. Returns nullptr if path is empty. + */ + static std::shared_ptr MakeFrom(const Path& path, const GradientPaint& gradient); + + ~Shape() override; + + GraphicType type() const override { + return GraphicType::Shape; + } + + void measureBounds(Rect* bounds) const override; + bool hitTest(RenderCache* cache, float x, float y) override; + bool getPath(Path* result) const override; + void prepare(RenderCache* cache) const override; + void draw(Canvas* canvas, RenderCache* cache) const override; + +private: + Path path = {}; + ShapeFill* fill = nullptr; + + Shape(Path path, ShapeFill* fill); }; } // namespace pag diff --git a/src/rendering/graphics/Snapshot.cpp b/src/rendering/graphics/Snapshot.cpp index 79840c2dbf..660f6e7896 100644 --- a/src/rendering/graphics/Snapshot.cpp +++ b/src/rendering/graphics/Snapshot.cpp @@ -23,17 +23,17 @@ namespace pag { bool Snapshot::hitTest(RenderCache* cache, float x, float y) const { - Point local = {x, y}; - if (!MapPointInverted(matrix, &local)) { - return false; - } - auto surface = Surface::Make(cache->getContext(), 1, 1); - if (surface == nullptr) { - return false; - } - auto canvas = surface->getCanvas(); - canvas->setMatrix(Matrix::MakeTrans(-local.x, -local.y)); - canvas->drawTexture(texture.get()); - return surface->hitTest(0, 0); + Point local = {x, y}; + if (!MapPointInverted(matrix, &local)) { + return false; + } + auto surface = Surface::Make(cache->getContext(), 1, 1); + if (surface == nullptr) { + return false; + } + auto canvas = surface->getCanvas(); + canvas->setMatrix(Matrix::MakeTrans(-local.x, -local.y)); + canvas->drawTexture(texture.get()); + return surface->hitTest(0, 0); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/graphics/Snapshot.h b/src/rendering/graphics/Snapshot.h index 22b0f05a86..9cdca667be 100644 --- a/src/rendering/graphics/Snapshot.h +++ b/src/rendering/graphics/Snapshot.h @@ -28,50 +28,50 @@ class RenderCache; * GPU. */ class Snapshot { - public: - /** - * Creates a new Snapshot with specified texture and matrix. - */ - explicit Snapshot(std::shared_ptr texture, const Matrix& matrix) - : texture(std::move(texture)), matrix(matrix) { - } +public: + /** + * Creates a new Snapshot with specified texture and matrix. + */ + explicit Snapshot(std::shared_ptr texture, const Matrix& matrix) + : texture(std::move(texture)), matrix(matrix) { + } - /** - * Returns the scaling factor of this snapshot to the original graphic content. - */ - float scaleFactor() const { - return 1 / matrix.getScaleX(); - } + /** + * Returns the scaling factor of this snapshot to the original graphic content. + */ + float scaleFactor() const { + return 1 / matrix.getScaleX(); + } - Matrix getMatrix() const { - return matrix; - } + Matrix getMatrix() const { + return matrix; + } - Texture* getTexture() const { - return texture.get(); - } + Texture* getTexture() const { + return texture.get(); + } - /** - * Returns memory usage information for this Snapshot. - */ - size_t memoryUsage() const { - return texture->memoryUsage(); - } + /** + * Returns memory usage information for this Snapshot. + */ + size_t memoryUsage() const { + return texture->memoryUsage(); + } - /** - * Evaluates the Snapshot to see if it overlaps or intersects with the specified point. The point - * is in the coordinate space of the Snapshot. This method always checks against the actual pixels - * of the Snapshot. - */ - bool hitTest(RenderCache* cache, float x, float y) const; + /** + * Evaluates the Snapshot to see if it overlaps or intersects with the specified point. The point + * is in the coordinate space of the Snapshot. This method always checks against the actual pixels + * of the Snapshot. + */ + bool hitTest(RenderCache* cache, float x, float y) const; - private: - std::shared_ptr texture = nullptr; - Matrix matrix = Matrix::I(); - ID assetID = 0; - uint64_t makerKey = 0; - Frame idleFrames = 0; +private: + std::shared_ptr texture = nullptr; + Matrix matrix = Matrix::I(); + ID assetID = 0; + uint64_t makerKey = 0; + Frame idleFrames = 0; - friend class RenderCache; + friend class RenderCache; }; } // namespace pag diff --git a/src/rendering/graphics/Text.cpp b/src/rendering/graphics/Text.cpp index f98a6cbf15..2debc523dc 100644 --- a/src/rendering/graphics/Text.cpp +++ b/src/rendering/graphics/Text.cpp @@ -25,116 +25,116 @@ namespace pag { static std::unique_ptr CreateFillPaint(const Glyph* glyph) { - if (glyph->getStyle() != TextStyle::Fill && glyph->getStyle() != TextStyle::StrokeAndFill) { - return nullptr; - } - auto fillPaint = new Paint(); - fillPaint->setStyle(PaintStyle::Fill); - fillPaint->setColor(glyph->getFillColor()); - fillPaint->setAlpha(glyph->getAlpha()); - return std::unique_ptr(fillPaint); + if (glyph->getStyle() != TextStyle::Fill && glyph->getStyle() != TextStyle::StrokeAndFill) { + return nullptr; + } + auto fillPaint = new Paint(); + fillPaint->setStyle(PaintStyle::Fill); + fillPaint->setColor(glyph->getFillColor()); + fillPaint->setAlpha(glyph->getAlpha()); + return std::unique_ptr(fillPaint); } static std::unique_ptr CreateStrokePaint(const Glyph* glyph) { - if (glyph->getStyle() != TextStyle::Stroke && glyph->getStyle() != TextStyle::StrokeAndFill) { - return nullptr; - } - auto strokePaint = new Paint(); - strokePaint->setStyle(PaintStyle::Stroke); - strokePaint->setColor(glyph->getStrokeColor()); - strokePaint->setAlpha(glyph->getAlpha()); - strokePaint->setStrokeWidth(glyph->getStrokeWidth()); - return std::unique_ptr(strokePaint); + if (glyph->getStyle() != TextStyle::Stroke && glyph->getStyle() != TextStyle::StrokeAndFill) { + return nullptr; + } + auto strokePaint = new Paint(); + strokePaint->setStyle(PaintStyle::Stroke); + strokePaint->setColor(glyph->getStrokeColor()); + strokePaint->setAlpha(glyph->getAlpha()); + strokePaint->setStrokeWidth(glyph->getStrokeWidth()); + return std::unique_ptr(strokePaint); } static std::unique_ptr MakeTextRun(const std::vector& glyphs) { - if (glyphs.empty()) { - return nullptr; - } - auto textRun = new TextRun(); - auto firstGlyph = glyphs[0]; - // Creates text paints. - textRun->paints[0] = CreateFillPaint(firstGlyph).release(); - textRun->paints[1] = CreateStrokePaint(firstGlyph).release(); - auto textStyle = firstGlyph->getStyle(); - if ((textStyle == TextStyle::StrokeAndFill && !firstGlyph->getStrokeOverFill()) || - textRun->paints[0] == nullptr) { - std::swap(textRun->paints[0], textRun->paints[1]); - } - // Creates text blob. - auto noTranslateMatrix = firstGlyph->getTotalMatrix(); - noTranslateMatrix.setTranslateX(0); - noTranslateMatrix.setTranslateY(0); - textRun->matrix = noTranslateMatrix; - noTranslateMatrix.invert(&noTranslateMatrix); - std::vector glyphIDs = {}; - std::vector positions = {}; - for (auto& glyph : glyphs) { - glyphIDs.push_back(glyph->getGlyphID()); - auto m = glyph->getTotalMatrix(); - m.postConcat(noTranslateMatrix); - positions.push_back({m.getTranslateX(), m.getTranslateY()}); - } - textRun->textFont = firstGlyph->getFont(); - textRun->glyphIDs = glyphIDs; - textRun->positions = positions; - return std::unique_ptr(textRun); + if (glyphs.empty()) { + return nullptr; + } + auto textRun = new TextRun(); + auto firstGlyph = glyphs[0]; + // Creates text paints. + textRun->paints[0] = CreateFillPaint(firstGlyph).release(); + textRun->paints[1] = CreateStrokePaint(firstGlyph).release(); + auto textStyle = firstGlyph->getStyle(); + if ((textStyle == TextStyle::StrokeAndFill && !firstGlyph->getStrokeOverFill()) || + textRun->paints[0] == nullptr) { + std::swap(textRun->paints[0], textRun->paints[1]); + } + // Creates text blob. + auto noTranslateMatrix = firstGlyph->getTotalMatrix(); + noTranslateMatrix.setTranslateX(0); + noTranslateMatrix.setTranslateY(0); + textRun->matrix = noTranslateMatrix; + noTranslateMatrix.invert(&noTranslateMatrix); + std::vector glyphIDs = {}; + std::vector positions = {}; + for (auto& glyph : glyphs) { + glyphIDs.push_back(glyph->getGlyphID()); + auto m = glyph->getTotalMatrix(); + m.postConcat(noTranslateMatrix); + positions.push_back({m.getTranslateX(), m.getTranslateY()}); + } + textRun->textFont = firstGlyph->getFont(); + textRun->glyphIDs = glyphIDs; + textRun->positions = positions; + return std::unique_ptr(textRun); } std::shared_ptr Text::MakeFrom(const std::vector& glyphs, const Rect* calculatedBounds) { - if (glyphs.empty()) { - return nullptr; - } - // 用 vector 存 key 的目的是让文字叠加顺序固定。 - // 不固定的话叠加区域的像素会不一样,肉眼看不出来,但是测试用例的结果不稳定。 - std::vector styleKeys = {}; - std::unordered_map, BytesHasher> styleMap = {}; - for (auto& glyph : glyphs) { - if (!glyph->isVisible()) { - continue; - } - BytesKey styleKey = {}; - glyph->computeStyleKey(&styleKey); - auto size = styleMap.size(); - styleMap[styleKey].push_back(glyph.get()); - if (styleMap.size() != size) { - styleKeys.push_back(styleKey); - } - } - bool hasAlpha = false; - Rect bounds = calculatedBounds ? *calculatedBounds : Rect::MakeEmpty(); - std::vector textRuns; - float maxStrokeWidth = 0; - for (auto& key : styleKeys) { - auto& glyphList = styleMap[key]; - Rect textBounds = Rect::MakeEmpty(); - for (auto glyph : glyphList) { - auto glyphBounds = glyph->getBounds(); - glyph->getMatrix().mapRect(&glyphBounds); - textBounds.join(glyphBounds); + if (glyphs.empty()) { + return nullptr; } - if (textBounds.isEmpty()) { - continue; - } - if (calculatedBounds == nullptr) { - bounds.join(textBounds); + // 用 vector 存 key 的目的是让文字叠加顺序固定。 + // 不固定的话叠加区域的像素会不一样,肉眼看不出来,但是测试用例的结果不稳定。 + std::vector styleKeys = {}; + std::unordered_map, BytesHasher> styleMap = {}; + for (auto& glyph : glyphs) { + if (!glyph->isVisible()) { + continue; + } + BytesKey styleKey = {}; + glyph->computeStyleKey(&styleKey); + auto size = styleMap.size(); + styleMap[styleKey].push_back(glyph.get()); + if (styleMap.size() != size) { + styleKeys.push_back(styleKey); + } } - auto strokeWidth = glyphList[0]->getStrokeWidth(); - if (strokeWidth > maxStrokeWidth) { - maxStrokeWidth = strokeWidth; + bool hasAlpha = false; + Rect bounds = calculatedBounds ? *calculatedBounds : Rect::MakeEmpty(); + std::vector textRuns; + float maxStrokeWidth = 0; + for (auto& key : styleKeys) { + auto& glyphList = styleMap[key]; + Rect textBounds = Rect::MakeEmpty(); + for (auto glyph : glyphList) { + auto glyphBounds = glyph->getBounds(); + glyph->getMatrix().mapRect(&glyphBounds); + textBounds.join(glyphBounds); + } + if (textBounds.isEmpty()) { + continue; + } + if (calculatedBounds == nullptr) { + bounds.join(textBounds); + } + auto strokeWidth = glyphList[0]->getStrokeWidth(); + if (strokeWidth > maxStrokeWidth) { + maxStrokeWidth = strokeWidth; + } + if (glyphList[0]->getAlpha() != Opaque) { + hasAlpha = true; + } + auto textRun = MakeTextRun(glyphList).release(); + textRuns.push_back(textRun); } - if (glyphList[0]->getAlpha() != Opaque) { - hasAlpha = true; + bounds.outset(maxStrokeWidth, maxStrokeWidth); + if (textRuns.empty()) { + return nullptr; } - auto textRun = MakeTextRun(glyphList).release(); - textRuns.push_back(textRun); - } - bounds.outset(maxStrokeWidth, maxStrokeWidth); - if (textRuns.empty()) { - return nullptr; - } - return std::shared_ptr(new Text(textRuns, bounds, hasAlpha)); + return std::shared_ptr(new Text(textRuns, bounds, hasAlpha)); } Text::Text(const std::vector& textRuns, const Rect& bounds, bool hasAlpha) @@ -142,118 +142,118 @@ Text::Text(const std::vector& textRuns, const Rect& bounds, bool hasAl } Text::~Text() { - for (auto& textRun : textRuns) { - delete textRun; - } + for (auto& textRun : textRuns) { + delete textRun; + } } void Text::measureBounds(Rect* rect) const { - *rect = bounds; + *rect = bounds; } static void ApplyPaintToPath(const Paint& paint, Path* path) { - if (paint.getStyle() == PaintStyle::Fill || path == nullptr) { - return; - } - auto strokePath = *path; - auto strokeEffect = PathEffect::MakeStroke(*paint.getStroke()); - if (strokeEffect) { - strokeEffect->applyTo(&strokePath); - } - if (paint.getStyle() == PaintStyle::Stroke) { - *path = strokePath; - } else { - path->addPath(strokePath); - } + if (paint.getStyle() == PaintStyle::Fill || path == nullptr) { + return; + } + auto strokePath = *path; + auto strokeEffect = PathEffect::MakeStroke(*paint.getStroke()); + if (strokeEffect) { + strokeEffect->applyTo(&strokePath); + } + if (paint.getStyle() == PaintStyle::Stroke) { + *path = strokePath; + } else { + path->addPath(strokePath); + } } bool Text::hitTest(RenderCache*, float x, float y) { - for (auto& textRun : textRuns) { - auto local = Point::Make(x, y); - Matrix invertMatrix = {}; - if (!textRun->matrix.invert(&invertMatrix)) { - continue; - } - invertMatrix.mapPoints(&local, 1); - Path glyphPath = {}; - int index = 0; - auto& textFont = textRun->textFont; - for (auto& glyphID : textRun->glyphIDs) { - textFont.getGlyphPath(glyphID, &glyphPath); - auto pos = textRun->positions[index++]; - auto localX = local.x - pos.x; - auto localY = local.y - pos.y; - for (auto paint : textRun->paints) { - if (paint == nullptr) { - continue; + for (auto& textRun : textRuns) { + auto local = Point::Make(x, y); + Matrix invertMatrix = {}; + if (!textRun->matrix.invert(&invertMatrix)) { + continue; } - auto tempPath = glyphPath; - ApplyPaintToPath(*paint, &tempPath); - if (tempPath.contains(localX, localY)) { - return true; + invertMatrix.mapPoints(&local, 1); + Path glyphPath = {}; + int index = 0; + auto& textFont = textRun->textFont; + for (auto& glyphID : textRun->glyphIDs) { + textFont.getGlyphPath(glyphID, &glyphPath); + auto pos = textRun->positions[index++]; + auto localX = local.x - pos.x; + auto localY = local.y - pos.y; + for (auto paint : textRun->paints) { + if (paint == nullptr) { + continue; + } + auto tempPath = glyphPath; + ApplyPaintToPath(*paint, &tempPath); + if (tempPath.contains(localX, localY)) { + return true; + } + } } - } } - } - return false; + return false; } bool Text::getPath(Path* path) const { - if (hasAlpha || path == nullptr) { - return false; - } - Path textPath = {}; - for (auto& textRun : textRuns) { - Path glyphPath = {}; - int index = 0; - auto& textFont = textRun->textFont; - for (auto& glyphID : textRun->glyphIDs) { - Path tempPath = {}; - if (!textFont.getGlyphPath(glyphID, &tempPath)) { + if (hasAlpha || path == nullptr) { return false; - } - auto pos = textRun->positions[index]; - tempPath.transform(Matrix::MakeTrans(pos.x, pos.y)); - glyphPath.addPath(tempPath); - index++; } - glyphPath.transform(textRun->matrix); - Path tempPath = glyphPath; - auto firstPaint = textRun->paints[0]; - auto secondPaint = textRun->paints[1]; - ApplyPaintToPath(*firstPaint, &tempPath); - textPath.addPath(tempPath); - if (secondPaint != nullptr) { - tempPath = glyphPath; - ApplyPaintToPath(*secondPaint, &tempPath); - textPath.addPath(tempPath); + Path textPath = {}; + for (auto& textRun : textRuns) { + Path glyphPath = {}; + int index = 0; + auto& textFont = textRun->textFont; + for (auto& glyphID : textRun->glyphIDs) { + Path tempPath = {}; + if (!textFont.getGlyphPath(glyphID, &tempPath)) { + return false; + } + auto pos = textRun->positions[index]; + tempPath.transform(Matrix::MakeTrans(pos.x, pos.y)); + glyphPath.addPath(tempPath); + index++; + } + glyphPath.transform(textRun->matrix); + Path tempPath = glyphPath; + auto firstPaint = textRun->paints[0]; + auto secondPaint = textRun->paints[1]; + ApplyPaintToPath(*firstPaint, &tempPath); + textPath.addPath(tempPath); + if (secondPaint != nullptr) { + tempPath = glyphPath; + ApplyPaintToPath(*secondPaint, &tempPath); + textPath.addPath(tempPath); + } } - } - path->addPath(textPath); - return true; + path->addPath(textPath); + return true; } void Text::prepare(RenderCache*) const { } void Text::draw(Canvas* canvas, RenderCache*) const { - drawTextRuns(static_cast(canvas), 0); - drawTextRuns(static_cast(canvas), 1); + drawTextRuns(static_cast(canvas), 0); + drawTextRuns(static_cast(canvas), 1); } void Text::drawTextRuns(Canvas* canvas, int paintIndex) const { - auto totalMatrix = canvas->getMatrix(); - for (auto& textRun : textRuns) { - auto textPaint = textRun->paints[paintIndex]; - if (!textPaint) { - continue; + auto totalMatrix = canvas->getMatrix(); + for (auto& textRun : textRuns) { + auto textPaint = textRun->paints[paintIndex]; + if (!textPaint) { + continue; + } + canvas->setMatrix(totalMatrix); + canvas->concat(textRun->matrix); + auto glyphs = &textRun->glyphIDs[0]; + auto positions = &textRun->positions[0]; + canvas->drawGlyphs(glyphs, positions, textRun->glyphIDs.size(), textRun->textFont, *textPaint); } canvas->setMatrix(totalMatrix); - canvas->concat(textRun->matrix); - auto glyphs = &textRun->glyphIDs[0]; - auto positions = &textRun->positions[0]; - canvas->drawGlyphs(glyphs, positions, textRun->glyphIDs.size(), textRun->textFont, *textPaint); - } - canvas->setMatrix(totalMatrix); } } // namespace pag diff --git a/src/rendering/graphics/Text.h b/src/rendering/graphics/Text.h index bad2f46a97..80ccac762d 100644 --- a/src/rendering/graphics/Text.h +++ b/src/rendering/graphics/Text.h @@ -23,46 +23,46 @@ namespace pag { class TextRun { - public: - ~TextRun() { - delete paints[0]; - delete paints[1]; - } +public: + ~TextRun() { + delete paints[0]; + delete paints[1]; + } - Matrix matrix = Matrix::I(); - Paint* paints[2] = {nullptr, nullptr}; - Font textFont = {}; - std::vector glyphIDs; - std::vector positions; + Matrix matrix = Matrix::I(); + Paint* paints[2] = {nullptr, nullptr}; + Font textFont = {}; + std::vector glyphIDs; + std::vector positions; }; class Text : public Graphic { - public: - /** - * Creates a text Graphic with specified glyphs. Returns nullptr if glyphs is empty or all of them - * are invisible. - */ - static std::shared_ptr MakeFrom(const std::vector& glyphs, - const Rect* calculatedBounds = nullptr); +public: + /** + * Creates a text Graphic with specified glyphs. Returns nullptr if glyphs is empty or all of them + * are invisible. + */ + static std::shared_ptr MakeFrom(const std::vector& glyphs, + const Rect* calculatedBounds = nullptr); - ~Text() override; + ~Text() override; - GraphicType type() const override { - return GraphicType::Text; - } + GraphicType type() const override { + return GraphicType::Text; + } - void measureBounds(Rect* rect) const override; - bool hitTest(RenderCache* cache, float x, float y) override; - bool getPath(Path* path) const override; - void prepare(RenderCache* cache) const override; - void draw(Canvas* canvas, RenderCache* cache) const override; + void measureBounds(Rect* rect) const override; + bool hitTest(RenderCache* cache, float x, float y) override; + bool getPath(Path* path) const override; + void prepare(RenderCache* cache) const override; + void draw(Canvas* canvas, RenderCache* cache) const override; - private: - std::vector textRuns; - Rect bounds = Rect::MakeEmpty(); - bool hasAlpha = false; +private: + std::vector textRuns; + Rect bounds = Rect::MakeEmpty(); + bool hasAlpha = false; - explicit Text(const std::vector& textRuns, const Rect& bounds, bool hasAlpha); - void drawTextRuns(Canvas* canvas, int paintIndex) const; + explicit Text(const std::vector& textRuns, const Rect& bounds, bool hasAlpha); + void drawTextRuns(Canvas* canvas, int paintIndex) const; }; } // namespace pag diff --git a/src/rendering/graphics/TextureProxy.h b/src/rendering/graphics/TextureProxy.h index 0377e33cf9..55f99fcc80 100644 --- a/src/rendering/graphics/TextureProxy.h +++ b/src/rendering/graphics/TextureProxy.h @@ -27,44 +27,44 @@ class RenderCache; * This class delays the acquisition of textures until they are actually required. */ class TextureProxy { - public: - TextureProxy(int width, int height) : _width(width), _height(height) { - } +public: + TextureProxy(int width, int height) : _width(width), _height(height) { + } - virtual ~TextureProxy() = default; + virtual ~TextureProxy() = default; - /** - * Returns the width of the texture. - */ - int width() const { - return _width; - } + /** + * Returns the width of the texture. + */ + int width() const { + return _width; + } - /** - * Returns the height of the texture. - */ - int height() const { - return _height; - } + /** + * Returns the height of the texture. + */ + int height() const { + return _height; + } - /** - * If true, this proxy returns the same texture every time. Otherwise, it creates a new texture - * every time. - */ - virtual bool cacheEnabled() const = 0; + /** + * If true, this proxy returns the same texture every time. Otherwise, it creates a new texture + * every time. + */ + virtual bool cacheEnabled() const = 0; - /** - * Prepares this TextureProxy for next getTexture() call. - */ - virtual void prepare(RenderCache* cache) const = 0; + /** + * Prepares this TextureProxy for next getTexture() call. + */ + virtual void prepare(RenderCache* cache) const = 0; - /** - * Instantiates and returns the backing texture associated with this proxy. - */ - virtual std::shared_ptr getTexture(RenderCache* cache) const = 0; + /** + * Instantiates and returns the backing texture associated with this proxy. + */ + virtual std::shared_ptr getTexture(RenderCache* cache) const = 0; - private: - int _width = 0; - int _height = 0; +private: + int _width = 0; + int _height = 0; }; } // namespace pag diff --git a/src/rendering/layers/PAGComposition.cpp b/src/rendering/layers/PAGComposition.cpp index ec4e208eaa..b1b06696c1 100644 --- a/src/rendering/layers/PAGComposition.cpp +++ b/src/rendering/layers/PAGComposition.cpp @@ -30,651 +30,651 @@ namespace pag { std::shared_ptr PAGComposition::Make(int width, int height) { - auto pagComposition = std::shared_ptr(new PAGComposition(width, height)); - pagComposition->weakThis = pagComposition; - return pagComposition; + auto pagComposition = std::shared_ptr(new PAGComposition(width, height)); + pagComposition->weakThis = pagComposition; + return pagComposition; } PAGComposition::PAGComposition(int width, int height) : PAGLayer(nullptr, nullptr), _width(width), _height(height) { - emptyComposition = new VectorComposition(); - emptyComposition->width = width; - emptyComposition->height = height; - emptyComposition->duration = INT64_MAX; - layer = PreComposeLayer::Wrap(emptyComposition).release(); - layerCache = LayerCache::Get(layer); - rootLocker = std::make_shared(); - contentVersion = 1; + emptyComposition = new VectorComposition(); + emptyComposition->width = width; + emptyComposition->height = height; + emptyComposition->duration = INT64_MAX; + layer = PreComposeLayer::Wrap(emptyComposition).release(); + layerCache = LayerCache::Get(layer); + rootLocker = std::make_shared(); + contentVersion = 1; } PAGComposition::PAGComposition(std::shared_ptr file, PreComposeLayer* layer) : PAGLayer(file, layer) { - if (layer != nullptr) { - _width = layer->composition->width; - _height = layer->composition->height; - if (file != nullptr) { - _frameRate = file->frameRate(); + if (layer != nullptr) { + _width = layer->composition->width; + _height = layer->composition->height; + if (file != nullptr) { + _frameRate = file->frameRate(); + } + _frameDuration = layer->duration; } - _frameDuration = layer->duration; - } } PAGComposition::~PAGComposition() { - removeAllLayers(); - if (emptyComposition) { - delete emptyComposition; // created by PAGComposition(width, height). - delete layer; // created by PAGComposition(width, height). - } + removeAllLayers(); + if (emptyComposition) { + delete emptyComposition; // created by PAGComposition(width, height). + delete layer; // created by PAGComposition(width, height). + } } int PAGComposition::width() const { - LockGuard autoLock(rootLocker); - return _width; + LockGuard autoLock(rootLocker); + return _width; } int PAGComposition::height() const { - LockGuard autoLock(rootLocker); - return _height; + LockGuard autoLock(rootLocker); + return _height; } void PAGComposition::setContentSize(int width, int height) { - LockGuard autoLock(rootLocker); - setContentSizeInternal(width, height); + LockGuard autoLock(rootLocker); + setContentSizeInternal(width, height); } int PAGComposition::widthInternal() const { - return _width; + return _width; } int PAGComposition::heightInternal() const { - return _height; + return _height; } void PAGComposition::setContentSizeInternal(int width, int height) { - if (_width == width && _height == height) { - return; - } - _width = width; - _height = height; - notifyModified(true); + if (_width == width && _height == height) { + return; + } + _width = width; + _height = height; + notifyModified(true); } int PAGComposition::numChildren() const { - LockGuard autoLock(rootLocker); - return static_cast(layers.size()); + LockGuard autoLock(rootLocker); + return static_cast(layers.size()); } std::shared_ptr PAGComposition::getLayerAt(int index) const { - LockGuard autoLock(rootLocker); - if (index >= 0 && static_cast(index) < layers.size()) { - return layers[index]; - } - LOGE("An index specified for a parameter was out of range."); - return nullptr; + LockGuard autoLock(rootLocker); + if (index >= 0 && static_cast(index) < layers.size()) { + return layers[index]; + } + LOGE("An index specified for a parameter was out of range."); + return nullptr; } int PAGComposition::getLayerIndexInternal(std::shared_ptr child) const { - int index = 0; - for (auto& layer : layers) { - if (layer == child) { - return index; + int index = 0; + for (auto& layer : layers) { + if (layer == child) { + return index; + } + index++; } - index++; - } - return -1; + return -1; } int PAGComposition::getLayerIndex(std::shared_ptr pagLayer) const { - LockGuard autoLock(rootLocker); - return getLayerIndexInternal(pagLayer); + LockGuard autoLock(rootLocker); + return getLayerIndexInternal(pagLayer); } void PAGComposition::setLayerIndex(std::shared_ptr pagLayer, int index) { - LockGuard autoLock(rootLocker); - doSetLayerIndex(pagLayer, index); + LockGuard autoLock(rootLocker); + doSetLayerIndex(pagLayer, index); } void PAGComposition::doSetLayerIndex(std::shared_ptr pagLayer, int index) { - if (index < 0 || static_cast(index) >= layers.size()) { - index = static_cast(layers.size()) - 1; - } - auto oldIndex = getLayerIndexInternal(pagLayer); - if (oldIndex < 0) { - LOGE("The supplied layer must be a child layer of the caller."); - return; - } - if (oldIndex == index) { - return; - } - layers.erase(layers.begin() + oldIndex); - layers.insert(layers.begin() + index, pagLayer); - notifyModified(true); + if (index < 0 || static_cast(index) >= layers.size()) { + index = static_cast(layers.size()) - 1; + } + auto oldIndex = getLayerIndexInternal(pagLayer); + if (oldIndex < 0) { + LOGE("The supplied layer must be a child layer of the caller."); + return; + } + if (oldIndex == index) { + return; + } + layers.erase(layers.begin() + oldIndex); + layers.insert(layers.begin() + index, pagLayer); + notifyModified(true); } bool PAGComposition::addLayer(std::shared_ptr pagLayer) { - if (pagLayer == nullptr) { - return false; - } - ScopedLock autoLock(rootLocker, pagLayer->rootLocker); - auto index = layers.size(); - if (pagLayer->_parent == this) { - index--; - } - return doAddLayer(pagLayer, static_cast(index)); + if (pagLayer == nullptr) { + return false; + } + ScopedLock autoLock(rootLocker, pagLayer->rootLocker); + auto index = layers.size(); + if (pagLayer->_parent == this) { + index--; + } + return doAddLayer(pagLayer, static_cast(index)); } bool PAGComposition::addLayerAt(std::shared_ptr pagLayer, int index) { - if (pagLayer == nullptr) { - return false; - } - ScopedLock autoLock(rootLocker, pagLayer->rootLocker); - if (index < 0 || static_cast(index) >= layers.size()) { - index = static_cast(layers.size()); - if (pagLayer->_parent == this) { - index--; + if (pagLayer == nullptr) { + return false; } - } - return doAddLayer(pagLayer, static_cast(index)); + ScopedLock autoLock(rootLocker, pagLayer->rootLocker); + if (index < 0 || static_cast(index) >= layers.size()) { + index = static_cast(layers.size()); + if (pagLayer->_parent == this) { + index--; + } + } + return doAddLayer(pagLayer, static_cast(index)); } bool PAGComposition::doAddLayer(std::shared_ptr pagLayer, int index) { - if (pagLayer.get() == this) { - LOGE("A layer cannot be added as a child of itself."); - return false; - } else if (pagLayer->layerType() == LayerType::PreCompose && - std::static_pointer_cast(pagLayer)->doContains(this)) { - LOGE( - "A layer cannot be added as a child to one of it's children " - "(or children's children, etc.)."); - return false; - } else if (pagLayer->stage == pagLayer.get()) { - LOGE("A stage cannot be added as a child to a layer."); - return false; - } - auto oldParent = pagLayer->_parent; - if (oldParent == this) { - doSetLayerIndex(pagLayer, index); + if (pagLayer.get() == this) { + LOGE("A layer cannot be added as a child of itself."); + return false; + } else if (pagLayer->layerType() == LayerType::PreCompose && + std::static_pointer_cast(pagLayer)->doContains(this)) { + LOGE( + "A layer cannot be added as a child to one of it's children " + "(or children's children, etc.)."); + return false; + } else if (pagLayer->stage == pagLayer.get()) { + LOGE("A stage cannot be added as a child to a layer."); + return false; + } + auto oldParent = pagLayer->_parent; + if (oldParent == this) { + doSetLayerIndex(pagLayer, index); + return true; + } + pagLayer->removeFromParentOrOwner(); + pagLayer->attachToTree(rootLocker, stage); + if (rootFile && file == pagLayer->file) { + pagLayer->onAddToRootFile(rootFile); + } + this->layers.insert(this->layers.begin() + index, pagLayer); + pagLayer->_parent = this; + notifyModified(true); + if (emptyComposition) { + updateDurationAndFrameRate(); + } return true; - } - pagLayer->removeFromParentOrOwner(); - pagLayer->attachToTree(rootLocker, stage); - if (rootFile && file == pagLayer->file) { - pagLayer->onAddToRootFile(rootFile); - } - this->layers.insert(this->layers.begin() + index, pagLayer); - pagLayer->_parent = this; - notifyModified(true); - if (emptyComposition) { - updateDurationAndFrameRate(); - } - return true; } bool PAGComposition::contains(std::shared_ptr pagLayer) const { - if (pagLayer == nullptr) { - return false; - } - ScopedLock autoLock(rootLocker, pagLayer->rootLocker); - return doContains(pagLayer.get()); + if (pagLayer == nullptr) { + return false; + } + ScopedLock autoLock(rootLocker, pagLayer->rootLocker); + return doContains(pagLayer.get()); } bool PAGComposition::doContains(pag::PAGLayer* target) const { - while (target) { - if (target == this) { - return true; + while (target) { + if (target == this) { + return true; + } + target = target->_parent; } - target = target->_parent; - } - return false; + return false; } std::shared_ptr PAGComposition::removeLayer(std::shared_ptr pagLayer) { - LockGuard autoLock(rootLocker); - auto index = getLayerIndexInternal(pagLayer); - if (index < 0) { - LOGE("The supplied layer must be a child of the caller."); - return nullptr; - } - return doRemoveLayer(index); + LockGuard autoLock(rootLocker); + auto index = getLayerIndexInternal(pagLayer); + if (index < 0) { + LOGE("The supplied layer must be a child of the caller."); + return nullptr; + } + return doRemoveLayer(index); } std::shared_ptr PAGComposition::removeLayerAt(int index) { - LockGuard autoLock(rootLocker); - if (index < 0 || static_cast(index) >= layers.size()) { - LOGE("An index specified for a parameter was out of range."); - return nullptr; - } - return doRemoveLayer(index); + LockGuard autoLock(rootLocker); + if (index < 0 || static_cast(index) >= layers.size()) { + LOGE("An index specified for a parameter was out of range."); + return nullptr; + } + return doRemoveLayer(index); } std::shared_ptr PAGComposition::doRemoveLayer(int index) { - auto layer = layers[index]; - if (rootFile && file == layer->file) { - layer->onRemoveFromRootFile(); - } - layer->detachFromTree(); - layer->_parent = nullptr; - layers.erase(layers.begin() + index); - notifyModified(true); - if (emptyComposition) { - updateDurationAndFrameRate(); - } - return layer; + auto layer = layers[index]; + if (rootFile && file == layer->file) { + layer->onRemoveFromRootFile(); + } + layer->detachFromTree(); + layer->_parent = nullptr; + layers.erase(layers.begin() + index); + notifyModified(true); + if (emptyComposition) { + updateDurationAndFrameRate(); + } + return layer; } void PAGComposition::removeAllLayers() { - LockGuard autoLock(rootLocker); - for (int i = static_cast(layers.size() - 1); i >= 0; i--) { - doRemoveLayer(i); - } + LockGuard autoLock(rootLocker); + for (int i = static_cast(layers.size() - 1); i >= 0; i--) { + doRemoveLayer(i); + } } void PAGComposition::swapLayer(std::shared_ptr pagLayer1, std::shared_ptr pagLayer2) { - LockGuard autoLock(rootLocker); - auto index1 = getLayerIndexInternal(pagLayer1); - auto index2 = getLayerIndexInternal(pagLayer2); - if (index1 == -1 || index2 == -1) { - LOGE("The supplied layer must be a child of the caller."); - return; - } - doSwapLayerAt(index1, index2); + LockGuard autoLock(rootLocker); + auto index1 = getLayerIndexInternal(pagLayer1); + auto index2 = getLayerIndexInternal(pagLayer2); + if (index1 == -1 || index2 == -1) { + LOGE("The supplied layer must be a child of the caller."); + return; + } + doSwapLayerAt(index1, index2); } void PAGComposition::swapLayerAt(int index1, int index2) { - LockGuard autoLock(rootLocker); - auto size = this->layers.size(); - if (index1 >= 0 && static_cast(index1) < size && index2 >= 0 && - static_cast(index2) < size) { - doSwapLayerAt(index1, index2); - } else { - LOGE("An index specified for a parameter was out of range."); - return; - } + LockGuard autoLock(rootLocker); + auto size = this->layers.size(); + if (index1 >= 0 && static_cast(index1) < size && index2 >= 0 && + static_cast(index2) < size) { + doSwapLayerAt(index1, index2); + } else { + LOGE("An index specified for a parameter was out of range."); + return; + } } void PAGComposition::doSwapLayerAt(int index1, int index2) { - if (index1 > index2) { - int temp = index2; - index2 = index1; - index1 = temp; - } else if (index1 == index2) { - return; - } - auto layer1 = layers[index1]; - auto layer2 = layers[index2]; - layers[index1] = layer2; - layers[index2] = layer1; - notifyModified(true); + if (index1 > index2) { + int temp = index2; + index2 = index1; + index1 = temp; + } else if (index1 == index2) { + return; + } + auto layer1 = layers[index1]; + auto layer2 = layers[index2]; + layers[index1] = layer2; + layers[index2] = layer1; + notifyModified(true); } ByteData* PAGComposition::audioBytes() const { - return static_cast(layer)->composition->audioBytes; + return static_cast(layer)->composition->audioBytes; } std::vector PAGComposition::audioMarkers() const { - std::vector result = {}; - for (auto marker : static_cast(layer)->composition->audioMarkers) { - result.push_back(marker); - } - return result; + std::vector result = {}; + for (auto marker : static_cast(layer)->composition->audioMarkers) { + result.push_back(marker); + } + return result; } Frame PAGComposition::audioStartTime() const { - auto preComposeLayer = static_cast(layer); - auto compositionOffset = preComposeLayer->compositionStartTime - layer->startTime + startFrame; - auto frame = preComposeLayer->composition->audioStartTime + compositionOffset; - return FrameToTime(frame, frameRateInternal()); + auto preComposeLayer = static_cast(layer); + auto compositionOffset = preComposeLayer->compositionStartTime - layer->startTime + startFrame; + auto frame = preComposeLayer->composition->audioStartTime + compositionOffset; + return FrameToTime(frame, frameRateInternal()); } std::vector> PAGComposition::getLayersBy( - std::function filterFunc) { - std::vector> result = {}; - FindLayers(filterFunc, &result, weakThis.lock()); - return result; +std::function filterFunc) { + std::vector> result = {}; + FindLayers(filterFunc, &result, weakThis.lock()); + return result; } void PAGComposition::FindLayers(std::function filterFunc, std::vector>* result, std::shared_ptr pagLayer) { - if (filterFunc(pagLayer.get())) { - result->push_back(pagLayer); - } - if (pagLayer->_trackMatteLayer) { - FindLayers(filterFunc, result, pagLayer->_trackMatteLayer); - } - if (pagLayer->layerType() == LayerType::PreCompose) { - for (auto& childLayer : static_cast(pagLayer.get())->layers) { - FindLayers(filterFunc, result, childLayer); + if (filterFunc(pagLayer.get())) { + result->push_back(pagLayer); + } + if (pagLayer->_trackMatteLayer) { + FindLayers(filterFunc, result, pagLayer->_trackMatteLayer); + } + if (pagLayer->layerType() == LayerType::PreCompose) { + for (auto& childLayer : static_cast(pagLayer.get())->layers) { + FindLayers(filterFunc, result, childLayer); + } } - } } Frame PAGComposition::childFrameToLocal(Frame childFrame, float childFrameRate) const { - auto localFrame = PAGLayer::childFrameToLocal(childFrame, childFrameRate); - auto compositionOffset = - static_cast(layer)->compositionStartTime - layer->startTime; - return localFrame + compositionOffset; + auto localFrame = PAGLayer::childFrameToLocal(childFrame, childFrameRate); + auto compositionOffset = + static_cast(layer)->compositionStartTime - layer->startTime; + return localFrame + compositionOffset; } Frame PAGComposition::localFrameToChild(Frame localFrame, float childFrameRate) const { - auto compositionOffset = - static_cast(layer)->compositionStartTime - layer->startTime; - auto childFrame = localFrame - compositionOffset; - return PAGLayer::localFrameToChild(childFrame, childFrameRate); + auto compositionOffset = + static_cast(layer)->compositionStartTime - layer->startTime; + auto childFrame = localFrame - compositionOffset; + return PAGLayer::localFrameToChild(childFrame, childFrameRate); } bool PAGComposition::hasClip() const { - return _width > 0 && _height > 0; + return _width > 0 && _height > 0; } Frame PAGComposition::frameDuration() const { - return _frameDuration; + return _frameDuration; } float PAGComposition::frameRateInternal() const { - return _frameRate; + return _frameRate; } bool PAGComposition::gotoTime(int64_t layerTime) { - auto changed = PAGLayer::gotoTime(layerTime); - auto compositionOffset = - static_cast(layer)->compositionStartTime - layer->startTime + startFrame; - /// 这里用floor取帧数是为了防止compositionOffsetTime变大导致layerTime变小导致显示帧数不正确。 - /// 比如layerTime = 100000 , compositionOffset = 1, frameRate = 30 - /// 此时如果取ceil compositionOffsetTime = 33334, subLayerTime = 66666,subLayerFrame = 1.9998 - /// 即显示第1帧, 但纯用frame计算时,gotoFrame = 2,因此此时不能取ceil,而要取floor来保证 - /// layerTime时间足够 - auto compositionOffsetTime = - static_cast(floor(compositionOffset * 1000000.0 / frameRateInternal())); - for (auto& layer : layers) { - if (layer->_excludedFromTimeline) { - continue; - } - if (layer->gotoTime(layerTime - compositionOffsetTime)) { - changed = true; - } - } - return changed; + auto changed = PAGLayer::gotoTime(layerTime); + auto compositionOffset = + static_cast(layer)->compositionStartTime - layer->startTime + startFrame; + /// 这里用floor取帧数是为了防止compositionOffsetTime变大导致layerTime变小导致显示帧数不正确。 + /// 比如layerTime = 100000 , compositionOffset = 1, frameRate = 30 + /// 此时如果取ceil compositionOffsetTime = 33334, subLayerTime = 66666,subLayerFrame = 1.9998 + /// 即显示第1帧, 但纯用frame计算时,gotoFrame = 2,因此此时不能取ceil,而要取floor来保证 + /// layerTime时间足够 + auto compositionOffsetTime = + static_cast(floor(compositionOffset * 1000000.0 / frameRateInternal())); + for (auto& layer : layers) { + if (layer->_excludedFromTimeline) { + continue; + } + if (layer->gotoTime(layerTime - compositionOffsetTime)) { + changed = true; + } + } + return changed; } void PAGComposition::draw(Recorder* recorder) { - if (!contentModified() && layerCache->contentStatic()) { - // 子项未发生任何修改且内容是静态的,可以使用缓存快速跳过所有子项绘制。 - getContent()->draw(recorder); - return; - } - auto preComposeLayer = static_cast(layer); - auto composition = preComposeLayer->composition; - if (composition->type() == CompositionType::Bitmap || - composition->type() == CompositionType::Video) { - auto layerFrame = layer->startTime + contentFrame; - auto compositionFrame = preComposeLayer->getCompositionFrame(layerFrame); - auto graphic = stage->getSequenceGraphic(composition, compositionFrame); - recorder->drawGraphic(graphic); - } - if (layers.empty()) { - return; - } - if (hasClip()) { - recorder->saveClip(0, 0, static_cast(_width), static_cast(_height)); - } - auto count = static_cast(layers.size()); - for (int i = 0; i < count; i++) { - auto& childLayer = layers[i]; - if (!childLayer->layerVisible) { - continue; - } - DrawChildLayer(recorder, childLayer.get()); - } - if (hasClip()) { - recorder->restore(); - } + if (!contentModified() && layerCache->contentStatic()) { + // 子项未发生任何修改且内容是静态的,可以使用缓存快速跳过所有子项绘制。 + getContent()->draw(recorder); + return; + } + auto preComposeLayer = static_cast(layer); + auto composition = preComposeLayer->composition; + if (composition->type() == CompositionType::Bitmap || + composition->type() == CompositionType::Video) { + auto layerFrame = layer->startTime + contentFrame; + auto compositionFrame = preComposeLayer->getCompositionFrame(layerFrame); + auto graphic = stage->getSequenceGraphic(composition, compositionFrame); + recorder->drawGraphic(graphic); + } + if (layers.empty()) { + return; + } + if (hasClip()) { + recorder->saveClip(0, 0, static_cast(_width), static_cast(_height)); + } + auto count = static_cast(layers.size()); + for (int i = 0; i < count; i++) { + auto& childLayer = layers[i]; + if (!childLayer->layerVisible) { + continue; + } + DrawChildLayer(recorder, childLayer.get()); + } + if (hasClip()) { + recorder->restore(); + } } void PAGComposition::DrawChildLayer(Recorder* recorder, PAGLayer* childLayer) { - auto filterModifier = childLayer->cacheFilters() ? nullptr : FilterModifier::Make(childLayer); - auto trackMatte = TrackMatteRenderer::Make(childLayer); - Transform extraTransform = {childLayer->layerMatrix, childLayer->layerOpacity}; - LayerRenderer::DrawLayer(recorder, childLayer->layer, - childLayer->contentFrame + childLayer->layer->startTime, filterModifier, - trackMatte.get(), childLayer, &extraTransform); + auto filterModifier = childLayer->cacheFilters() ? nullptr : FilterModifier::Make(childLayer); + auto trackMatte = TrackMatteRenderer::Make(childLayer); + Transform extraTransform = {childLayer->layerMatrix, childLayer->layerOpacity}; + LayerRenderer::DrawLayer(recorder, childLayer->layer, + childLayer->contentFrame + childLayer->layer->startTime, filterModifier, + trackMatte.get(), childLayer, &extraTransform); } void PAGComposition::measureBounds(Rect* bounds) { - if (!contentModified() && layerCache->contentStatic()) { - getContent()->measureBounds(bounds); - return; - } - bounds->setEmpty(); - auto composition = static_cast(layer)->composition; - if (composition->type() == CompositionType::Bitmap || - composition->type() == CompositionType::Video) { - getContent()->measureBounds(bounds); - } - for (auto& childLayer : layers) { - if (!childLayer->layerVisible) { - continue; - } - Rect layerBounds = {}; - MeasureChildLayer(&layerBounds, childLayer.get()); - bounds->join(layerBounds); - } - if (hasClip() && !bounds->isEmpty()) { - auto clipBounds = Rect::MakeXYWH(0, 0, _width, _height); - if (!bounds->intersect(clipBounds)) { - bounds->setEmpty(); - } - } + if (!contentModified() && layerCache->contentStatic()) { + getContent()->measureBounds(bounds); + return; + } + bounds->setEmpty(); + auto composition = static_cast(layer)->composition; + if (composition->type() == CompositionType::Bitmap || + composition->type() == CompositionType::Video) { + getContent()->measureBounds(bounds); + } + for (auto& childLayer : layers) { + if (!childLayer->layerVisible) { + continue; + } + Rect layerBounds = {}; + MeasureChildLayer(&layerBounds, childLayer.get()); + bounds->join(layerBounds); + } + if (hasClip() && !bounds->isEmpty()) { + auto clipBounds = Rect::MakeXYWH(0, 0, _width, _height); + if (!bounds->intersect(clipBounds)) { + bounds->setEmpty(); + } + } } void PAGComposition::MeasureChildLayer(Rect* bounds, PAGLayer* childLayer) { - std::unique_ptr trackMatteBounds = nullptr; - if (childLayer->_trackMatteLayer != nullptr) { - trackMatteBounds = std::unique_ptr(new Rect()); - trackMatteBounds->setEmpty(); - auto trackMatteLayer = childLayer->_trackMatteLayer; - auto layerFrame = trackMatteLayer->contentFrame + trackMatteLayer->layer->startTime; - auto filterModifier = FilterModifier::Make(trackMatteLayer.get()); - Transform extraTransform = {trackMatteLayer->layerMatrix, trackMatteLayer->layerOpacity}; - LayerRenderer::MeasureLayerBounds(trackMatteBounds.get(), trackMatteLayer->layer, layerFrame, - filterModifier, nullptr, trackMatteLayer.get(), - &extraTransform); - } - auto layerFrame = childLayer->contentFrame + childLayer->layer->startTime; - auto filterModifier = FilterModifier::Make(childLayer->layer, layerFrame); - Transform extraTransform = {childLayer->layerMatrix, childLayer->layerOpacity}; - LayerRenderer::MeasureLayerBounds(bounds, childLayer->layer, layerFrame, filterModifier, - trackMatteBounds.get(), childLayer, &extraTransform); + std::unique_ptr trackMatteBounds = nullptr; + if (childLayer->_trackMatteLayer != nullptr) { + trackMatteBounds = std::unique_ptr(new Rect()); + trackMatteBounds->setEmpty(); + auto trackMatteLayer = childLayer->_trackMatteLayer; + auto layerFrame = trackMatteLayer->contentFrame + trackMatteLayer->layer->startTime; + auto filterModifier = FilterModifier::Make(trackMatteLayer.get()); + Transform extraTransform = {trackMatteLayer->layerMatrix, trackMatteLayer->layerOpacity}; + LayerRenderer::MeasureLayerBounds(trackMatteBounds.get(), trackMatteLayer->layer, layerFrame, + filterModifier, nullptr, trackMatteLayer.get(), + &extraTransform); + } + auto layerFrame = childLayer->contentFrame + childLayer->layer->startTime; + auto filterModifier = FilterModifier::Make(childLayer->layer, layerFrame); + Transform extraTransform = {childLayer->layerMatrix, childLayer->layerOpacity}; + LayerRenderer::MeasureLayerBounds(bounds, childLayer->layer, layerFrame, filterModifier, + trackMatteBounds.get(), childLayer, &extraTransform); } std::vector> PAGComposition::getLayersByName( - const std::string& layerName) { - LockGuard autoLock(rootLocker); - if (layerName.empty()) { - return {}; - } - std::vector> result = - getLayersBy([=](PAGLayer* pagLayer) -> bool { return pagLayer->layerName() == layerName; }); - return result; +const std::string& layerName) { + LockGuard autoLock(rootLocker); + if (layerName.empty()) { + return {}; + } + std::vector> result = + getLayersBy([=](PAGLayer* pagLayer) -> bool { return pagLayer->layerName() == layerName; }); + return result; } std::vector> PAGComposition::getLayersUnderPoint(float localX, - float localY) { - LockGuard autoLock(rootLocker); - std::vector> results; - getLayersUnderPointInternal(localX, localY, &results); - return results; +float localY) { + LockGuard autoLock(rootLocker); + std::vector> results; + getLayersUnderPointInternal(localX, localY, &results); + return results; } bool PAGComposition::GetTrackMatteLayerAtPoint(PAGLayer* childLayer, float x, float y, - std::vector>* results) { - // trackMatteLayer 处于时间轴不可见的情况下也要当做空区域处理,永远不取消遮罩作用。当 trackMatte - // 为空时,配合 inverted 的遮罩类型,表示保留全部目标图层。 - bool contains = false; - Transform trackMatteTransform = {}; - auto trackMatteLayer = childLayer->_trackMatteLayer.get(); - if (trackMatteLayer->getTransform(&trackMatteTransform)) { - Point local = {x, y}; - MapPointInverted(trackMatteTransform.matrix, &local); - Rect trackMatteBounds = {}; - trackMatteLayer->measureBounds(&trackMatteBounds); - contains = trackMatteBounds.contains(local.x, local.y); - if (contains) { - results->push_back(childLayer->_trackMatteLayer); - } - } - auto trackMatteType = childLayer->layer->trackMatteType; - auto inverse = (trackMatteType == TrackMatteType::AlphaInverted || - trackMatteType == TrackMatteType::LumaInverted); - return (contains != inverse); + std::vector>* results) { + // trackMatteLayer 处于时间轴不可见的情况下也要当做空区域处理,永远不取消遮罩作用。当 trackMatte + // 为空时,配合 inverted 的遮罩类型,表示保留全部目标图层。 + bool contains = false; + Transform trackMatteTransform = {}; + auto trackMatteLayer = childLayer->_trackMatteLayer.get(); + if (trackMatteLayer->getTransform(&trackMatteTransform)) { + Point local = {x, y}; + MapPointInverted(trackMatteTransform.matrix, &local); + Rect trackMatteBounds = {}; + trackMatteLayer->measureBounds(&trackMatteBounds); + contains = trackMatteBounds.contains(local.x, local.y); + if (contains) { + results->push_back(childLayer->_trackMatteLayer); + } + } + auto trackMatteType = childLayer->layer->trackMatteType; + auto inverse = (trackMatteType == TrackMatteType::AlphaInverted || + trackMatteType == TrackMatteType::LumaInverted); + return (contains != inverse); } bool PAGComposition::GetChildLayerAtPoint(PAGLayer* childLayer, float x, float y, - std::vector>* results) { - Transform layerTransform = {}; - if (!childLayer->getTransform(&layerTransform)) { - return false; - } - Point localPoint = {x, y}; - MapPointInverted(layerTransform.matrix, &localPoint); - auto mask = childLayer->layerCache->getMasks(childLayer->contentFrame); - if (mask) { - auto maskBounds = mask->getBounds(); - auto inverse = mask->isInverseFillType(); - if (maskBounds.contains(localPoint.x, localPoint.y) == inverse) { - return false; - } - } - - bool success = false; - if (childLayer->layerType() == LayerType::PreCompose) { - success = static_cast(childLayer) + std::vector>* results) { + Transform layerTransform = {}; + if (!childLayer->getTransform(&layerTransform)) { + return false; + } + Point localPoint = {x, y}; + MapPointInverted(layerTransform.matrix, &localPoint); + auto mask = childLayer->layerCache->getMasks(childLayer->contentFrame); + if (mask) { + auto maskBounds = mask->getBounds(); + auto inverse = mask->isInverseFillType(); + if (maskBounds.contains(localPoint.x, localPoint.y) == inverse) { + return false; + } + } + + bool success = false; + if (childLayer->layerType() == LayerType::PreCompose) { + success = static_cast(childLayer) ->getLayersUnderPointInternal(localPoint.x, localPoint.y, results); - } - if (!success) { - Rect childBounds = {}; - childLayer->measureBounds(&childBounds); - success = childBounds.contains(localPoint.x, localPoint.y); - } - return success; + } + if (!success) { + Rect childBounds = {}; + childLayer->measureBounds(&childBounds); + success = childBounds.contains(localPoint.x, localPoint.y); + } + return success; } bool PAGComposition::getLayersUnderPointInternal(float x, float y, - std::vector>* results) { - auto bounds = Rect::MakeWH(static_cast(_width), static_cast(_height)); - if (hasClip() && !bounds.contains(x, y)) { - return false; - } - bool found = false; - for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { - auto childLayer = layers[i]; - if (!childLayer->layerVisible) { - continue; + std::vector>* results) { + auto bounds = Rect::MakeWH(static_cast(_width), static_cast(_height)); + if (hasClip() && !bounds.contains(x, y)) { + return false; } - if (childLayer->_trackMatteLayer && - !GetTrackMatteLayerAtPoint(childLayer.get(), x, y, results)) { - continue; + bool found = false; + for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { + auto childLayer = layers[i]; + if (!childLayer->layerVisible) { + continue; + } + if (childLayer->_trackMatteLayer && + !GetTrackMatteLayerAtPoint(childLayer.get(), x, y, results)) { + continue; + } + auto success = GetChildLayerAtPoint(childLayer.get(), x, y, results); + if (success) { + results->push_back(childLayer); + found = true; + } } - auto success = GetChildLayerAtPoint(childLayer.get(), x, y, results); - if (success) { - results->push_back(childLayer); - found = true; - } - } - return found; + return found; } bool PAGComposition::cacheFilters() const { - return layerCache->cacheFilters() && !contentModified() && layerCache->contentStatic(); + return layerCache->cacheFilters() && !contentModified() && layerCache->contentStatic(); } void PAGComposition::invalidateCacheScale() { - if (stage == nullptr) { - return; - } - PAGLayer::invalidateCacheScale(); - for (auto& layer : layers) { - if (layer->_trackMatteLayer) { - layer->_trackMatteLayer->invalidateCacheScale(); + if (stage == nullptr) { + return; + } + PAGLayer::invalidateCacheScale(); + for (auto& layer : layers) { + if (layer->_trackMatteLayer) { + layer->_trackMatteLayer->invalidateCacheScale(); + } + layer->invalidateCacheScale(); } - layer->invalidateCacheScale(); - } } void PAGComposition::onAddToStage(PAGStage* pagStage) { - PAGLayer::onAddToStage(pagStage); - for (auto& layer : layers) { - layer->onAddToStage(pagStage); - } + PAGLayer::onAddToStage(pagStage); + for (auto& layer : layers) { + layer->onAddToStage(pagStage); + } } void PAGComposition::onRemoveFromStage() { - PAGLayer::onRemoveFromStage(); - for (auto& layer : layers) { - layer->onRemoveFromStage(); - } + PAGLayer::onRemoveFromStage(); + for (auto& layer : layers) { + layer->onRemoveFromStage(); + } } void PAGComposition::onAddToRootFile(PAGFile* pagFile) { - PAGLayer::onAddToRootFile(pagFile); - for (auto& layer : layers) { - if (layer->file == file) { - layer->onAddToRootFile(pagFile); + PAGLayer::onAddToRootFile(pagFile); + for (auto& layer : layers) { + if (layer->file == file) { + layer->onAddToRootFile(pagFile); + } } - } } void PAGComposition::onRemoveFromRootFile() { - PAGLayer::onRemoveFromRootFile(); - for (auto& layer : layers) { - if (layer->file == file) { - layer->onRemoveFromRootFile(); + PAGLayer::onRemoveFromRootFile(); + for (auto& layer : layers) { + if (layer->file == file) { + layer->onRemoveFromRootFile(); + } } - } } void PAGComposition::onTimelineChanged() { - for (auto& layer : layers) { - layer->onTimelineChanged(); - if (layer->_trackMatteLayer != nullptr) { - layer->_trackMatteLayer->onTimelineChanged(); + for (auto& layer : layers) { + layer->onTimelineChanged(); + if (layer->_trackMatteLayer != nullptr) { + layer->_trackMatteLayer->onTimelineChanged(); + } } - } } void PAGComposition::updateRootLocker(std::shared_ptr locker) { - PAGLayer::updateRootLocker(locker); - for (auto& layer : layers) { - layer->updateRootLocker(locker); - } + PAGLayer::updateRootLocker(locker); + for (auto& layer : layers) { + layer->updateRootLocker(locker); + } } void PAGComposition::updateDurationAndFrameRate() { - int64_t layerMaxTimeDuration = 1; - float layerMaxFrameRate = layers.empty() ? 60 : 1; - for (auto& layer : layers) { - auto layerTimeDuration = layer->startTimeInternal() + layer->durationInternal(); - if (layerTimeDuration > layerMaxTimeDuration) { - layerMaxTimeDuration = layerTimeDuration; - } - auto layerFrameRate = layer->frameRateInternal(); - if (layerFrameRate > layerMaxFrameRate) { - layerMaxFrameRate = layerFrameRate; - } - } - bool changed = false; - auto layerMaxFrameDuration = TimeToFrame(layerMaxTimeDuration, layerMaxFrameRate); - if (_frameDuration != layerMaxFrameDuration) { - _frameDuration = layerMaxFrameDuration; - changed = true; - } - if (_frameRate != layerMaxFrameRate) { - _frameRate = layerMaxFrameRate; - changed = true; - } - if (changed && _parent && _parent->emptyComposition) { - _parent->updateDurationAndFrameRate(); - } + int64_t layerMaxTimeDuration = 1; + float layerMaxFrameRate = layers.empty() ? 60 : 1; + for (auto& layer : layers) { + auto layerTimeDuration = layer->startTimeInternal() + layer->durationInternal(); + if (layerTimeDuration > layerMaxTimeDuration) { + layerMaxTimeDuration = layerTimeDuration; + } + auto layerFrameRate = layer->frameRateInternal(); + if (layerFrameRate > layerMaxFrameRate) { + layerMaxFrameRate = layerFrameRate; + } + } + bool changed = false; + auto layerMaxFrameDuration = TimeToFrame(layerMaxTimeDuration, layerMaxFrameRate); + if (_frameDuration != layerMaxFrameDuration) { + _frameDuration = layerMaxFrameDuration; + changed = true; + } + if (_frameRate != layerMaxFrameRate) { + _frameRate = layerMaxFrameRate; + changed = true; + } + if (changed && _parent && _parent->emptyComposition) { + _parent->updateDurationAndFrameRate(); + } } } // namespace pag diff --git a/src/rendering/layers/PAGImageLayer.cpp b/src/rendering/layers/PAGImageLayer.cpp index c00234ccc5..764bdfaef6 100644 --- a/src/rendering/layers/PAGImageLayer.cpp +++ b/src/rendering/layers/PAGImageLayer.cpp @@ -29,12 +29,12 @@ namespace pag { std::shared_ptr PAGImageLayer::Make(int width, int height, int64_t duration) { - if (width <= 0 || height <= 0 || duration <= 0) { - return nullptr; - } - auto imageLayer = std::shared_ptr(new PAGImageLayer(width, height, duration)); - imageLayer->weakThis = imageLayer; - return imageLayer; + if (width <= 0 || height <= 0 || duration <= 0) { + return nullptr; + } + auto imageLayer = std::shared_ptr(new PAGImageLayer(width, height, duration)); + imageLayer->weakThis = imageLayer; + return imageLayer; } PAGImageLayer::PAGImageLayer(std::shared_ptr file, ImageLayer* layer) @@ -42,622 +42,623 @@ PAGImageLayer::PAGImageLayer(std::shared_ptr file, ImageLayer* layer) } PAGImageLayer::PAGImageLayer(int width, int height, int64_t duration) : PAGLayer(nullptr, nullptr) { - emptyImageLayer = new ImageLayer(); - emptyImageLayer->transform = Transform2D::MakeDefault(); - emptyImageLayer->imageBytes = new ImageBytes(); - emptyImageLayer->imageBytes->width = width; - emptyImageLayer->imageBytes->height = height; - emptyImageLayer->imageBytes->fileBytes = ByteData::Make(0).release(); - emptyImageLayer->duration = TimeToFrame(duration, 60); - - layer = emptyImageLayer; - layerCache = LayerCache::Get(layer); - rootLocker = std::make_shared(); - contentVersion = 1; - _editableIndex = 0; - imageHolder = std::make_shared(); - imageHolder->addLayer(this); - replacement = new ImageReplacement(emptyImageLayer, imageHolder.get(), _editableIndex); + emptyImageLayer = new ImageLayer(); + emptyImageLayer->transform = Transform2D::MakeDefault(); + emptyImageLayer->imageBytes = new ImageBytes(); + emptyImageLayer->imageBytes->width = width; + emptyImageLayer->imageBytes->height = height; + emptyImageLayer->imageBytes->fileBytes = ByteData::Make(0).release(); + emptyImageLayer->duration = TimeToFrame(duration, 60); + + layer = emptyImageLayer; + layerCache = LayerCache::Get(layer); + rootLocker = std::make_shared(); + contentVersion = 1; + _editableIndex = 0; + imageHolder = std::make_shared(); + imageHolder->addLayer(this); + replacement = new ImageReplacement(emptyImageLayer, imageHolder.get(), _editableIndex); } PAGImageLayer::~PAGImageLayer() { - replaceImageInternal(nullptr); - delete replacement; - if (emptyImageLayer) { - delete emptyImageLayer->imageBytes; - delete emptyImageLayer; - } + replaceImageInternal(nullptr); + delete replacement; + if (emptyImageLayer) { + delete emptyImageLayer->imageBytes; + delete emptyImageLayer; + } } template Frame CalculateMaxFrame(const std::vector*>& keyframes) { - Frame maxFrame = 0; - for (auto& keyframe : keyframes) { - if (keyframe->startValue > maxFrame) { - maxFrame = static_cast(keyframe->startValue); - } - if (keyframe->endValue > maxFrame) { - maxFrame = static_cast(keyframe->endValue); + Frame maxFrame = 0; + for (auto& keyframe : keyframes) { + if (keyframe->startValue > maxFrame) { + maxFrame = static_cast(keyframe->startValue); + } + if (keyframe->endValue > maxFrame) { + maxFrame = static_cast(keyframe->endValue); + } } - } - return maxFrame; + return maxFrame; } int64_t PAGImageLayer::contentDuration() { - LockGuard autoLock(rootLocker); - Frame maxFrame = 0; - float frameRate = 60; - if (rootFile) { - frameRate = rootFile->frameRateInternal(); - auto property = getContentTimeRemap(); - if (!property->animatable()) { - return 0; - } - auto timeRemap = static_cast*>(property); - maxFrame = CalculateMaxFrame(timeRemap->keyframes); - } else { - auto imageFillRule = static_cast(layer)->imageFillRule; - if (imageFillRule == nullptr || imageFillRule->timeRemap == nullptr || - !imageFillRule->timeRemap->animatable()) { - return FrameToTime(layer->duration, frameRate); + LockGuard autoLock(rootLocker); + Frame maxFrame = 0; + float frameRate = 60; + if (rootFile) { + frameRate = rootFile->frameRateInternal(); + auto property = getContentTimeRemap(); + if (!property->animatable()) { + return 0; + } + auto timeRemap = static_cast*>(property); + maxFrame = CalculateMaxFrame(timeRemap->keyframes); + } else { + auto imageFillRule = static_cast(layer)->imageFillRule; + if (imageFillRule == nullptr || imageFillRule->timeRemap == nullptr || + !imageFillRule->timeRemap->animatable()) { + return FrameToTime(layer->duration, frameRate); + } + frameRate = frameRateInternal(); + auto timeRemap = static_cast*>(imageFillRule->timeRemap); + // timeRemap编码过程中是开区间,实际使用过程中是闭区间,计算完后需要-1 + maxFrame = CalculateMaxFrame(timeRemap->keyframes) - 1; } - frameRate = frameRateInternal(); - auto timeRemap = static_cast*>(imageFillRule->timeRemap); - // timeRemap编码过程中是开区间,实际使用过程中是闭区间,计算完后需要-1 - maxFrame = CalculateMaxFrame(timeRemap->keyframes) - 1; - } - return FrameToTime(maxFrame + 1, frameRate); + return FrameToTime(maxFrame + 1, frameRate); } class FrameRange { - public: - FrameRange(pag::Frame startFrame, pag::Frame endFrame, pag::Frame duration) - : startFrame(startFrame), endFrame(endFrame), duration(duration) { - } - - static std::vector FromTimeRemap(std::vector*> keyframes, - Layer* layer) { - std::vector frameRanges; - if (keyframes[0]->startTime > layer->startTime) { - auto startTime = keyframes[0]->startValue; - auto duration = keyframes[0]->startTime - layer->startTime; - frameRanges.emplace_back(startTime, startTime, duration); +public: + FrameRange(pag::Frame startFrame, pag::Frame endFrame, pag::Frame duration) + : startFrame(startFrame), endFrame(endFrame), duration(duration) { } - for (auto& keyframe : keyframes) { - auto startTime = keyframe->startValue; - auto endTime = keyframe->endValue; - auto duration = keyframe->endTime - keyframe->startTime; - frameRanges.emplace_back(startTime, endTime, duration); - } - auto keyframe = keyframes.back(); - if (keyframe->endTime < layer->startTime + layer->duration) { - auto endTime = keyframe->endValue; - auto duration = layer->startTime + layer->duration - keyframe->endTime; - frameRanges.emplace_back(endTime, endTime, duration); - } - - for (auto index = frameRanges.size() - 1; index >= 1; index--) { - if (frameRanges[index].startFrame == frameRanges[index].endFrame && - frameRanges[index - 1].startFrame == frameRanges[index - 1].endFrame && - frameRanges[index].startFrame == frameRanges[index - 1].startFrame) { - frameRanges[index - 1].duration += frameRanges[index].duration; - frameRanges.erase(frameRanges.begin() + index); - } - } - - for (auto index = frameRanges.size() - 1; index >= 1; index--) { - if (frameRanges[index].duration == 1) { - frameRanges[index - 1].duration++; - frameRanges.erase(frameRanges.begin() + index); - } - } - return frameRanges; - } - - pag::Frame startFrame = 0; - pag::Frame endFrame = 0; - pag::Frame duration = 0; + + static std::vector FromTimeRemap(std::vector*> keyframes, + Layer* layer) { + std::vector frameRanges; + if (keyframes[0]->startTime > layer->startTime) { + auto startTime = keyframes[0]->startValue; + auto duration = keyframes[0]->startTime - layer->startTime; + frameRanges.emplace_back(startTime, startTime, duration); + } + for (auto& keyframe : keyframes) { + auto startTime = keyframe->startValue; + auto endTime = keyframe->endValue; + auto duration = keyframe->endTime - keyframe->startTime; + frameRanges.emplace_back(startTime, endTime, duration); + } + auto keyframe = keyframes.back(); + if (keyframe->endTime < layer->startTime + layer->duration) { + auto endTime = keyframe->endValue; + auto duration = layer->startTime + layer->duration - keyframe->endTime; + frameRanges.emplace_back(endTime, endTime, duration); + } + + for (auto index = frameRanges.size() - 1; index >= 1; index--) { + if (frameRanges[index].startFrame == frameRanges[index].endFrame && + frameRanges[index - 1].startFrame == frameRanges[index - 1].endFrame && + frameRanges[index].startFrame == frameRanges[index - 1].startFrame) { + frameRanges[index - 1].duration += frameRanges[index].duration; + frameRanges.erase(frameRanges.begin() + index); + } + } + + for (auto index = frameRanges.size() - 1; index >= 1; index--) { + if (frameRanges[index].duration == 1) { + frameRanges[index - 1].duration++; + frameRanges.erase(frameRanges.begin() + index); + } + } + return frameRanges; + } + + pag::Frame startFrame = 0; + pag::Frame endFrame = 0; + pag::Frame duration = 0; }; std::vector PAGImageLayer::getVideoRanges() const { - LockGuard autoLock(rootLocker); - auto frameRate = frameRateInternal(); - auto imageFillRule = static_cast(layer)->imageFillRule; - auto timeRemap = (imageFillRule == nullptr) ? nullptr : imageFillRule->timeRemap; - if (timeRemap == nullptr || !timeRemap->animatable()) { - auto duration = FrameToTime(layer->duration, frameRate); - PAGVideoRange videoRange = {0, duration, duration}; - return {videoRange}; - } - - auto keyframes = static_cast*>(timeRemap)->keyframes; - auto frameRanges = FrameRange::FromTimeRemap(keyframes, layer); - - std::vector ranges; - for (auto frameRange : frameRanges) { - auto startTime = FrameToTime(frameRange.startFrame, frameRate); - auto endTime = FrameToTime(frameRange.endFrame, frameRate); - auto duration = FrameToTime(frameRange.duration, frameRate); - ranges.emplace_back(startTime, endTime, duration); - } - return ranges; + LockGuard autoLock(rootLocker); + auto frameRate = frameRateInternal(); + auto imageFillRule = static_cast(layer)->imageFillRule; + auto timeRemap = (imageFillRule == nullptr) ? nullptr : imageFillRule->timeRemap; + if (timeRemap == nullptr || !timeRemap->animatable()) { + auto duration = FrameToTime(layer->duration, frameRate); + PAGVideoRange videoRange = {0, duration, duration}; + return {videoRange}; + } + + auto keyframes = static_cast*>(timeRemap)->keyframes; + auto frameRanges = FrameRange::FromTimeRemap(keyframes, layer); + + std::vector ranges; + for (auto frameRange : frameRanges) { + auto startTime = FrameToTime(frameRange.startFrame, frameRate); + auto endTime = FrameToTime(frameRange.endFrame, frameRate); + auto duration = FrameToTime(frameRange.duration, frameRate); + ranges.emplace_back(startTime, endTime, duration); + } + return ranges; } void PAGImageLayer::replaceImage(std::shared_ptr image) { - LockGuard autoLock(rootLocker); - replaceImageInternal(image); + LockGuard autoLock(rootLocker); + replaceImageInternal(image); } void PAGImageLayer::replaceImageInternal(std::shared_ptr image) { - if (imageHolder == nullptr) { - return; - } - if (stage) { - auto oldPAGImage = imageHolder->getImage(_editableIndex); - auto pagLayers = imageHolder->getLayers(_editableIndex); - for (auto& layer : pagLayers) { - if (oldPAGImage) { - stage->removeReference(oldPAGImage.get(), layer); - } - if (image) { - stage->addReference(image.get(), layer); - } - } - } - imageHolder->setImage(_editableIndex, image); - std::vector imageLayers = {}; - if (rootFile) { - auto layers = rootFile->getLayersByEditableIndexInternal(_editableIndex, LayerType::Image); - for (auto& pagLayer : layers) { - imageLayers.push_back(static_cast(pagLayer.get())); - } - } else { - imageLayers.push_back(this); - } - std::for_each(imageLayers.begin(), imageLayers.end(), [](PAGImageLayer* imageLayer) { - imageLayer->notifyModified(true); - imageLayer->invalidateCacheScale(); - }); + if (imageHolder == nullptr) { + return; + } + if (stage) { + auto oldPAGImage = imageHolder->getImage(_editableIndex); + auto pagLayers = imageHolder->getLayers(_editableIndex); + for (auto& layer : pagLayers) { + if (oldPAGImage) { + stage->removeReference(oldPAGImage.get(), layer); + } + if (image) { + stage->addReference(image.get(), layer); + } + } + } + imageHolder->setImage(_editableIndex, image); + std::vector imageLayers = {}; + if (rootFile) { + auto layers = rootFile->getLayersByEditableIndexInternal(_editableIndex, LayerType::Image); + for (auto& pagLayer : layers) { + imageLayers.push_back(static_cast(pagLayer.get())); + } + } else { + imageLayers.push_back(this); + } + std::for_each(imageLayers.begin(), imageLayers.end(), [](PAGImageLayer* imageLayer) { + imageLayer->notifyModified(true); + imageLayer->invalidateCacheScale(); + }); } Content* PAGImageLayer::getContent() { - return hasPAGImage() ? replacement : layerCache->getContent(contentFrame); + return hasPAGImage() ? replacement : layerCache->getContent(contentFrame); } bool PAGImageLayer::contentModified() const { - return hasPAGImage(); + return hasPAGImage(); } bool PAGImageLayer::cacheFilters() const { - return layerCache->cacheFilters() && !hasPAGImage(); + return layerCache->cacheFilters() && !hasPAGImage(); } void PAGImageLayer::onAddToRootFile(PAGFile* pagFile) { - PAGLayer::onAddToRootFile(pagFile); - imageHolder = pagFile->imageHolder; - imageHolder->addLayer(this); - replacement = - new ImageReplacement(static_cast(layer), imageHolder.get(), _editableIndex); + PAGLayer::onAddToRootFile(pagFile); + imageHolder = pagFile->imageHolder; + imageHolder->addLayer(this); + replacement = + new ImageReplacement(static_cast(layer), imageHolder.get(), _editableIndex); } void PAGImageLayer::onRemoveFromRootFile() { - PAGLayer::onRemoveFromRootFile(); - imageHolder->removeLayer(this); - delete replacement; - replacement = nullptr; - imageHolder = nullptr; - contentTimeRemap = nullptr; + PAGLayer::onRemoveFromRootFile(); + imageHolder->removeLayer(this); + delete replacement; + replacement = nullptr; + imageHolder = nullptr; + contentTimeRemap = nullptr; } void PAGImageLayer::onTimelineChanged() { - contentTimeRemap = nullptr; + contentTimeRemap = nullptr; } bool PAGImageLayer::contentVisible() { - if (rootFile) { - auto timeRange = getVisibleRangeInFile(); - auto stretchedContentFrame = rootFile->stretchedContentFrame(); - return timeRange.start <= stretchedContentFrame && stretchedContentFrame <= timeRange.end; - } else { - auto frame = TimeToFrame(contentDuration(), frameRateInternal()); - return 0 <= contentFrame && contentFrame < frame; - } + if (rootFile) { + auto timeRange = getVisibleRangeInFile(); + auto stretchedContentFrame = rootFile->stretchedContentFrame(); + return timeRange.start <= stretchedContentFrame && stretchedContentFrame <= timeRange.end; + } else { + auto frame = TimeToFrame(contentDuration(), frameRateInternal()); + return 0 <= contentFrame && contentFrame < frame; + } } int64_t PAGImageLayer::getCurrentContentTime(int64_t layerTime) { - int64_t replacementTime = 0; - if (rootFile) { - if (contentVisible()) { - auto timeRemap = getContentTimeRemap(); - auto replacementFrame = timeRemap->getValueAt(rootFile->stretchedContentFrame()); - replacementTime = - static_cast(ceil(replacementFrame * 1000000.0 / rootFile->frameRateInternal())); + int64_t replacementTime = 0; + if (rootFile) { + if (contentVisible()) { + auto timeRemap = getContentTimeRemap(); + auto replacementFrame = timeRemap->getValueAt(rootFile->stretchedContentFrame()); + replacementTime = + static_cast(ceil(replacementFrame * 1000000.0 / rootFile->frameRateInternal())); + } else { + replacementTime = + FrameToTime(rootFile->stretchedContentFrame(), rootFile->frameRateInternal()); + } } else { - replacementTime = - FrameToTime(rootFile->stretchedContentFrame(), rootFile->frameRateInternal()); + replacementTime = layerTime - startTimeInternal(); } - } else { - replacementTime = layerTime - startTimeInternal(); - } - return replacementTime; + return replacementTime; } static Keyframe* CreateKeyframe(float startTime, float endTime, float startValue, float endValue) { - auto newKeyframe = new SingleEaseKeyframe(); - newKeyframe->startTime = startTime; - newKeyframe->endTime = endTime; - newKeyframe->startValue = startValue; - newKeyframe->endValue = endValue; - return newKeyframe; + auto newKeyframe = new SingleEaseKeyframe(); + newKeyframe->startTime = startTime; + newKeyframe->endTime = endTime; + newKeyframe->startValue = startValue; + newKeyframe->endValue = endValue; + return newKeyframe; } static void CutKeyframe(Keyframe* keyframe, Frame position, bool cutLeft) { - if (keyframe->interpolationType == KeyframeInterpolationType::Bezier) { - auto t = static_cast(position - keyframe->startTime) / - static_cast(keyframe->endTime - keyframe->startTime); - auto p1 = Interpolate(Point::Zero(), keyframe->bezierOut[0], t); - auto bc = Interpolate(keyframe->bezierOut[0], keyframe->bezierIn[0], t); - auto p5 = Interpolate(keyframe->bezierIn[0], Point::Make(1, 1), t); - auto p2 = Interpolate(p1, bc, t); - auto p4 = Interpolate(bc, p5, t); + if (keyframe->interpolationType == KeyframeInterpolationType::Bezier) { + auto t = static_cast(position - keyframe->startTime) / + static_cast(keyframe->endTime - keyframe->startTime); + auto p1 = Interpolate(Point::Zero(), keyframe->bezierOut[0], t); + auto bc = Interpolate(keyframe->bezierOut[0], keyframe->bezierIn[0], t); + auto p5 = Interpolate(keyframe->bezierIn[0], Point::Make(1, 1), t); + auto p2 = Interpolate(p1, bc, t); + auto p4 = Interpolate(bc, p5, t); + if (cutLeft) { + keyframe->bezierOut[0] = p4; + keyframe->bezierIn[0] = p5; + } else { + keyframe->bezierOut[0] = p1; + keyframe->bezierIn[0] = p2; + } + } + auto midValue = keyframe->getValueAt(position); if (cutLeft) { - keyframe->bezierOut[0] = p4; - keyframe->bezierIn[0] = p5; + keyframe->startValue = midValue; + keyframe->startTime = position; } else { - keyframe->bezierOut[0] = p1; - keyframe->bezierIn[0] = p2; + keyframe->endValue = midValue; + keyframe->endTime = position; } - } - auto midValue = keyframe->getValueAt(position); - if (cutLeft) { - keyframe->startValue = midValue; - keyframe->startTime = position; - } else { - keyframe->endValue = midValue; - keyframe->endTime = position; - } } bool PAGImageLayer::hasPAGImage() const { - return imageHolder && imageHolder->hasImage(_editableIndex); + return imageHolder && imageHolder->hasImage(_editableIndex); } std::shared_ptr PAGImageLayer::getPAGImage() const { - if (!imageHolder) { - return nullptr; - } - return imageHolder->getImage(_editableIndex); + if (!imageHolder) { + return nullptr; + } + return imageHolder->getImage(_editableIndex); } // 输出的时间轴不包含startTime std::unique_ptr> PAGImageLayer::copyContentTimeRemap() { - std::vector*> keyframes = {}; - auto imageFillRule = static_cast(layer)->imageFillRule; - if (imageFillRule == nullptr || imageFillRule->timeRemap == nullptr || - !imageFillRule->timeRemap->animatable()) { - auto newKeyframe = CreateKeyframe(layer->startTime, layer->startTime + layer->duration - 1, - layer->startTime, layer->startTime + layer->duration - 1); - keyframes.push_back(newKeyframe); - newKeyframe->interpolationType = KeyframeInterpolationType::Linear; - - } else { - auto timeRemap = static_cast*>(imageFillRule->timeRemap); - for (auto& keyFrame : timeRemap->keyframes) { - Keyframe* newKeyframe = nullptr; - if (keyFrame->interpolationType == KeyframeInterpolationType::Hold) { - newKeyframe = new Keyframe(); - } else { - newKeyframe = new SingleEaseKeyframe(); - } - newKeyframe->startValue = static_cast(keyFrame->startValue); - newKeyframe->endValue = static_cast(keyFrame->endValue); - newKeyframe->startTime = keyFrame->startTime; - newKeyframe->endTime = keyFrame->endTime; - newKeyframe->interpolationType = keyFrame->interpolationType; - newKeyframe->bezierIn.assign(keyFrame->bezierIn.begin(), keyFrame->bezierIn.end()); - newKeyframe->bezierOut.assign(keyFrame->bezierOut.begin(), keyFrame->bezierOut.end()); - newKeyframe->spatialIn = keyFrame->spatialIn; - newKeyframe->spatialOut = keyFrame->spatialOut; - keyframes.push_back(newKeyframe); - } - } - - return std::unique_ptr>(new AnimatableProperty(keyframes)); + std::vector*> keyframes = {}; + auto imageFillRule = static_cast(layer)->imageFillRule; + if (imageFillRule == nullptr || imageFillRule->timeRemap == nullptr || + !imageFillRule->timeRemap->animatable()) { + auto newKeyframe = CreateKeyframe(layer->startTime, layer->startTime + layer->duration - 1, + layer->startTime, layer->startTime + layer->duration - 1); + keyframes.push_back(newKeyframe); + newKeyframe->interpolationType = KeyframeInterpolationType::Linear; + + } else { + auto timeRemap = static_cast*>(imageFillRule->timeRemap); + for (auto& keyFrame : timeRemap->keyframes) { + Keyframe* newKeyframe = nullptr; + if (keyFrame->interpolationType == KeyframeInterpolationType::Hold) { + newKeyframe = new Keyframe(); + } else { + newKeyframe = new SingleEaseKeyframe(); + } + newKeyframe->startValue = static_cast(keyFrame->startValue); + newKeyframe->endValue = static_cast(keyFrame->endValue); + newKeyframe->startTime = keyFrame->startTime; + newKeyframe->endTime = keyFrame->endTime; + newKeyframe->interpolationType = keyFrame->interpolationType; + newKeyframe->bezierIn.assign(keyFrame->bezierIn.begin(), keyFrame->bezierIn.end()); + newKeyframe->bezierOut.assign(keyFrame->bezierOut.begin(), keyFrame->bezierOut.end()); + newKeyframe->spatialIn = keyFrame->spatialIn; + newKeyframe->spatialOut = keyFrame->spatialOut; + keyframes.push_back(newKeyframe); + } + } + + return std::unique_ptr>(new AnimatableProperty(keyframes)); } Property* PAGImageLayer::getContentTimeRemap() { - if (contentTimeRemap == nullptr && rootFile) { - auto visibleRange = getVisibleRangeInFile(); - if (visibleRange.start == visibleRange.end || visibleRange.end < 0 || - visibleRange.start > rootFile->stretchedFrameDuration() - 1) { - // 在File层级不可见 - auto property = new Property(); - property->value = 0; - contentTimeRemap = std::unique_ptr>(property); - } else { - auto property = copyContentTimeRemap(); - if (property != nullptr) { - for (auto& keyFrame : property->keyframes) { - keyFrame->startTime -= layer->startTime; - keyFrame->endTime -= layer->startTime; + if (contentTimeRemap == nullptr && rootFile) { + auto visibleRange = getVisibleRangeInFile(); + if (visibleRange.start == visibleRange.end || visibleRange.end < 0 || + visibleRange.start > rootFile->stretchedFrameDuration() - 1) { + // 在File层级不可见 + auto property = new Property(); + property->value = 0; + contentTimeRemap = std::unique_ptr>(property); + } else { + auto property = copyContentTimeRemap(); + if (property != nullptr) { + for (auto& keyFrame : property->keyframes) { + keyFrame->startTime -= layer->startTime; + keyFrame->endTime -= layer->startTime; + } + } + double frameScale = + static_cast(visibleRange.end - visibleRange.start + 1) / frameDuration(); + BuildContentTimeRemap(property.get(), rootFile, visibleRange, frameScale); + contentTimeRemap = std::move(property); } - } - double frameScale = - static_cast(visibleRange.end - visibleRange.start + 1) / frameDuration(); - BuildContentTimeRemap(property.get(), rootFile, visibleRange, frameScale); - contentTimeRemap = std::move(property); } - } - return contentTimeRemap.get(); + return contentTimeRemap.get(); } Frame PAGImageLayer::ScaleTimeRemap(AnimatableProperty* property, const TimeRange& visibleRange, double frameScale, Frame fileEndFrame) { - float minValue = FLT_MAX; - float maxValue = 0; - auto& keyframes = property->keyframes; - for (int i = static_cast(keyframes.size() - 1); i >= 0; i--) { - auto& keyframe = keyframes[i]; - keyframe->startTime = - visibleRange.start + static_cast(round(keyframe->startTime * frameScale)); - auto duration = keyframe->endTime - keyframe->startTime + 1; - // 由于是闭区间,计算完后需要-1 - keyframe->endTime = visibleRange.start + - static_cast(round((keyframe->startTime + duration) * frameScale)) - - 1; - keyframe->startValue = static_cast(round(keyframe->startValue * frameScale)); - auto valueLength = keyframe->endValue - keyframe->startValue + 1; - // 由于是闭区间,计算完后需要-1 - keyframe->endValue = - static_cast(round((keyframe->startValue + valueLength) * frameScale)) - 1; - // 由于startTime和endTime都是帧号,因此当startTime == fileEndFrame 和 endTime == 0都有意义 - if (keyframe->startTime > fileEndFrame) { - delete keyframe; - keyframes.erase(keyframes.begin() + i); - continue; - } - if (keyframe->endTime < 0) { - delete keyframe; - keyframes.erase(keyframes.begin() + i); - continue; - } - if (keyframe->endTime > fileEndFrame) { - CutKeyframe(keyframe, fileEndFrame, false); - } - if (keyframe->startTime < 0) { - CutKeyframe(keyframe, 0, true); - } - minValue = std::floor(std::min(keyframe->startValue, minValue)); - minValue = std::floor(std::min(keyframe->endValue, minValue)); - maxValue = std::floor(std::max(keyframe->startValue, maxValue)); - maxValue = std::floor(std::max(keyframe->endValue, maxValue)); - } - for (auto& keyframe : keyframes) { - keyframe->startValue -= minValue; - keyframe->endValue -= minValue; - } - // 当keyframes所有的区间都在File的显示区间之外时,补一个keyFrame,防止后续计算错误。 - if (keyframes.size() == 0) { - auto newKeyframe = CreateKeyframe(visibleRange.start, visibleRange.end, 0, - visibleRange.end - visibleRange.start); - keyframes.push_back(newKeyframe); - newKeyframe->initialize(); - maxValue = visibleRange.end - visibleRange.start; - minValue = 0; - } - return (maxValue - minValue + 1); + float minValue = FLT_MAX; + float maxValue = 0; + auto& keyframes = property->keyframes; + for (int i = static_cast(keyframes.size() - 1); i >= 0; i--) { + auto& keyframe = keyframes[i]; + keyframe->startTime = + visibleRange.start + static_cast(round(keyframe->startTime * frameScale)); + auto duration = keyframe->endTime - keyframe->startTime + 1; + // 由于是闭区间,计算完后需要-1 + keyframe->endTime = visibleRange.start + + static_cast(round((keyframe->startTime + duration) * frameScale)) - + 1; + keyframe->startValue = static_cast(round(keyframe->startValue * frameScale)); + auto valueLength = keyframe->endValue - keyframe->startValue + 1; + // 由于是闭区间,计算完后需要-1 + keyframe->endValue = + static_cast(round((keyframe->startValue + valueLength) * frameScale)) - 1; + // 由于startTime和endTime都是帧号,因此当startTime == fileEndFrame 和 endTime == 0都有意义 + if (keyframe->startTime > fileEndFrame) { + delete keyframe; + keyframes.erase(keyframes.begin() + i); + continue; + } + if (keyframe->endTime < 0) { + delete keyframe; + keyframes.erase(keyframes.begin() + i); + continue; + } + if (keyframe->endTime > fileEndFrame) { + CutKeyframe(keyframe, fileEndFrame, false); + } + if (keyframe->startTime < 0) { + CutKeyframe(keyframe, 0, true); + } + minValue = std::floor(std::min(keyframe->startValue, minValue)); + minValue = std::floor(std::min(keyframe->endValue, minValue)); + maxValue = std::floor(std::max(keyframe->startValue, maxValue)); + maxValue = std::floor(std::max(keyframe->endValue, maxValue)); + } + for (auto& keyframe : keyframes) { + keyframe->startValue -= minValue; + keyframe->endValue -= minValue; + } + // 当keyframes所有的区间都在File的显示区间之外时,补一个keyFrame,防止后续计算错误。 + if (keyframes.size() == 0) { + auto newKeyframe = CreateKeyframe(visibleRange.start, visibleRange.end, 0, + visibleRange.end - visibleRange.start); + keyframes.push_back(newKeyframe); + newKeyframe->initialize(); + maxValue = visibleRange.end - visibleRange.start; + minValue = 0; + } + return (maxValue - minValue + 1); } // 输出的时间轴不包含startTime void PAGImageLayer::BuildContentTimeRemap(AnimatableProperty* property, PAGFile* fileOwner, - const TimeRange& visibleRange, double frameScale) { - auto fileDuration = fileOwner->frameDuration(); - auto fileStretchedDuration = fileOwner->stretchedFrameDuration(); - auto hasRepeat = (fileOwner->_timeStretchMode == PAGTimeStretchMode::Repeat || - fileOwner->_timeStretchMode == PAGTimeStretchMode::RepeatInverted) && - (fileDuration < fileStretchedDuration); - auto fileEndFrame = hasRepeat ? fileDuration - 1 : fileStretchedDuration - 1; - auto scaleDuration = ScaleTimeRemap(property, visibleRange, frameScale, fileEndFrame); - auto& keyframes = property->keyframes; - // 补齐头尾的空缺。 - auto firstKeyframe = keyframes.front(); - if (firstKeyframe->startTime > 0) { - auto newKeyframe = CreateKeyframe(0, firstKeyframe->startTime, firstKeyframe->startValue, - firstKeyframe->startValue); - keyframes.insert(keyframes.begin(), newKeyframe); - newKeyframe->initialize(); - } - auto lastKeyframe = keyframes.back(); - if (lastKeyframe->endTime < fileEndFrame) { - auto newKeyframe = CreateKeyframe(lastKeyframe->endTime, fileEndFrame, lastKeyframe->endValue, - lastKeyframe->endValue); - keyframes.push_back(newKeyframe); - newKeyframe->initialize(); - } - if (hasRepeat) { - // 处理file存在repeat拉伸的情况。 - ExpandPropertyByRepeat(property, fileOwner, scaleDuration); - } + const TimeRange& visibleRange, double frameScale) { + auto fileDuration = fileOwner->frameDuration(); + auto fileStretchedDuration = fileOwner->stretchedFrameDuration(); + auto hasRepeat = (fileOwner->_timeStretchMode == PAGTimeStretchMode::Repeat || + fileOwner->_timeStretchMode == PAGTimeStretchMode::RepeatInverted) && + (fileDuration < fileStretchedDuration); + auto fileEndFrame = hasRepeat ? fileDuration - 1 : fileStretchedDuration - 1; + auto scaleDuration = ScaleTimeRemap(property, visibleRange, frameScale, fileEndFrame); + auto& keyframes = property->keyframes; + // 补齐头尾的空缺。 + auto firstKeyframe = keyframes.front(); + if (firstKeyframe->startTime > 0) { + auto newKeyframe = CreateKeyframe(0, firstKeyframe->startTime, firstKeyframe->startValue, + firstKeyframe->startValue); + keyframes.insert(keyframes.begin(), newKeyframe); + newKeyframe->initialize(); + } + auto lastKeyframe = keyframes.back(); + if (lastKeyframe->endTime < fileEndFrame) { + auto newKeyframe = CreateKeyframe(lastKeyframe->endTime, fileEndFrame, lastKeyframe->endValue, + lastKeyframe->endValue); + keyframes.push_back(newKeyframe); + newKeyframe->initialize(); + } + if (hasRepeat) { + // 处理file存在repeat拉伸的情况。 + ExpandPropertyByRepeat(property, fileOwner, scaleDuration); + } } TimeRange PAGImageLayer::getVisibleRangeInFile() { - TimeRange timeRange = {}; - timeRange.start = startFrame; - timeRange.end = startFrame + frameDuration() - 1; - auto parent = _parent; - auto childFrameRate = frameRateInternal(); - while (parent) { - timeRange.start = parent->childFrameToLocal(timeRange.start, childFrameRate); - timeRange.end = parent->childFrameToLocal(timeRange.end, childFrameRate); - if (parent == rootFile) { - break; - } - childFrameRate = parent->frameRateInternal(); - parent = parent->_parent; - } - timeRange.start -= rootFile->startFrame; - timeRange.end -= rootFile->startFrame; - if (timeRange.start > timeRange.end) { - std::swap(timeRange.start, timeRange.end); - } - return timeRange; + TimeRange timeRange = {}; + timeRange.start = startFrame; + timeRange.end = startFrame + frameDuration() - 1; + auto parent = _parent; + auto childFrameRate = frameRateInternal(); + while (parent) { + timeRange.start = parent->childFrameToLocal(timeRange.start, childFrameRate); + timeRange.end = parent->childFrameToLocal(timeRange.end, childFrameRate); + if (parent == rootFile) { + break; + } + childFrameRate = parent->frameRateInternal(); + parent = parent->_parent; + } + timeRange.start -= rootFile->startFrame; + timeRange.end -= rootFile->startFrame; + if (timeRange.start > timeRange.end) { + std::swap(timeRange.start, timeRange.end); + } + return timeRange; } void PAGImageLayer::ExpandPropertyByRepeat(AnimatableProperty* property, PAGFile* fileOwner, - Frame contentDuration) { - std::vector*> newKeyframes = {}; - auto fileStretchedDuration = fileOwner->stretchedFrameDuration(); - auto fileDuration = fileOwner->frameDuration(); - int count = 1; - bool end = false; - while (!end) { - for (auto& keyframe : property->keyframes) { - Keyframe* newKeyframe = new SingleEaseKeyframe(); - *newKeyframe = *keyframe; - newKeyframe->startTime += fileDuration * count; - newKeyframe->endTime += fileDuration * count; - newKeyframe->startValue += contentDuration * count; - newKeyframe->endValue += contentDuration * count; - newKeyframes.push_back(newKeyframe); - newKeyframe->initialize(); - if (newKeyframe->endTime > fileStretchedDuration - 1) { - CutKeyframe(newKeyframe, fileStretchedDuration - 1, false); - } - if (newKeyframe->endTime == fileStretchedDuration - 1) { - end = true; - break; - } - } - count++; - } - for (auto& keyframe : newKeyframes) { - property->keyframes.push_back(keyframe); - } + Frame contentDuration) { + std::vector*> newKeyframes = {}; + auto fileStretchedDuration = fileOwner->stretchedFrameDuration(); + auto fileDuration = fileOwner->frameDuration(); + int count = 1; + bool end = false; + while (!end) { + for (auto& keyframe : property->keyframes) { + Keyframe* newKeyframe = new SingleEaseKeyframe(); + *newKeyframe = *keyframe; + newKeyframe->startTime += fileDuration * count; + newKeyframe->endTime += fileDuration * count; + newKeyframe->startValue += contentDuration * count; + newKeyframe->endValue += contentDuration * count; + newKeyframes.push_back(newKeyframe); + newKeyframe->initialize(); + if (newKeyframe->endTime > fileStretchedDuration - 1) { + CutKeyframe(newKeyframe, fileStretchedDuration - 1, false); + } + if (newKeyframe->endTime == fileStretchedDuration - 1) { + end = true; + break; + } + } + count++; + } + for (auto& keyframe : newKeyframes) { + property->keyframes.push_back(keyframe); + } } int64_t PAGImageLayer::contentTimeToLayer(int64_t replacementTime) { - LockGuard autoLock(rootLocker); - if (rootFile == nullptr) { - return replacementTime; - } - auto replacementFrame = TimeToFrame(replacementTime, rootFile->frameRateInternal()); - auto fileFrame = getFrameFromTimeRemap(replacementFrame); - auto localFrame = fileFrameToLocalFrame(fileFrame); - if (localFrame > startFrame + stretchedFrameDuration()) { - localFrame = startFrame + stretchedFrameDuration(); - } - if (localFrame < startFrame) { - localFrame = startFrame; - } - return FrameToTime(localFrame, frameRateInternal()); + LockGuard autoLock(rootLocker); + if (rootFile == nullptr) { + return replacementTime; + } + auto replacementFrame = TimeToFrame(replacementTime, rootFile->frameRateInternal()); + auto fileFrame = getFrameFromTimeRemap(replacementFrame); + auto localFrame = fileFrameToLocalFrame(fileFrame); + if (localFrame > startFrame + stretchedFrameDuration()) { + localFrame = startFrame + stretchedFrameDuration(); + } + if (localFrame < startFrame) { + localFrame = startFrame; + } + return FrameToTime(localFrame, frameRateInternal()); } int64_t PAGImageLayer::layerTimeToContent(int64_t layerTime) { - LockGuard autoLock(rootLocker); - if (rootFile == nullptr) { - return layerTime; - } - auto localFrame = TimeToFrame(layerTime, frameRateInternal()); - auto fileFrame = localFrameToFileFrame(localFrame); - auto timeRemap = getContentTimeRemap(); - auto replacementFrame = timeRemap->getValueAt(fileFrame); - return FrameToTime(replacementFrame, rootFile->frameRateInternal()); + LockGuard autoLock(rootLocker); + if (rootFile == nullptr) { + return layerTime; + } + auto localFrame = TimeToFrame(layerTime, frameRateInternal()); + auto fileFrame = localFrameToFileFrame(localFrame); + auto timeRemap = getContentTimeRemap(); + auto replacementFrame = timeRemap->getValueAt(fileFrame); + return FrameToTime(replacementFrame, rootFile->frameRateInternal()); } int64_t PAGImageLayer::localFrameToFileFrame(int64_t localFrame) const { - if (rootFile == nullptr) { - return localFrame; - } - auto owner = getTimelineOwner(); - auto childFrameRate = frameRateInternal(); - while (owner != nullptr) { - localFrame = owner->childFrameToLocal(localFrame, childFrameRate); - childFrameRate = owner->frameRateInternal(); - if (owner == rootFile) { - break; + if (rootFile == nullptr) { + return localFrame; + } + auto owner = getTimelineOwner(); + auto childFrameRate = frameRateInternal(); + while (owner != nullptr) { + localFrame = owner->childFrameToLocal(localFrame, childFrameRate); + childFrameRate = owner->frameRateInternal(); + if (owner == rootFile) { + break; + } + owner = owner->getTimelineOwner(); } - owner = owner->getTimelineOwner(); - } - return localFrame; + return localFrame; } int64_t PAGImageLayer::fileFrameToLocalFrame(int64_t fileFrame) const { - std::vector list = {}; - auto owner = getTimelineOwner(); - while (owner != nullptr) { - list.push_back(owner); - if (owner == rootFile) { - break; - } - owner = owner->getTimelineOwner(); - } - for (int i = static_cast(list.size() - 1); i >= 0; i--) { - auto childFrameRate = i > 0 ? list[i - 1]->frameRateInternal() : frameRateInternal(); - fileFrame = list[i]->localFrameToChild(fileFrame, childFrameRate); - } - return fileFrame; + std::vector list = {}; + auto owner = getTimelineOwner(); + while (owner != nullptr) { + list.push_back(owner); + if (owner == rootFile) { + break; + } + owner = owner->getTimelineOwner(); + } + for (int i = static_cast(list.size() - 1); i >= 0; i--) { + auto childFrameRate = i > 0 ? list[i - 1]->frameRateInternal() : frameRateInternal(); + fileFrame = list[i]->localFrameToChild(fileFrame, childFrameRate); + } + return fileFrame; } Frame GetFrameFromBezierTimeRemap(Frame value, Keyframe* frame, pag::AnimatableProperty* property) { - auto current = (frame->startTime + frame->endTime) / 2; - auto start = frame->startTime; - auto end = frame->endTime; - // 二分查找 - while (start <= end) { - auto currentValue = static_cast(property->getValueAt(current)); - if (currentValue > value) { - end = current - 1; - } else if (currentValue < value) { - start = current + 1; - } else { - break; + auto current = (frame->startTime + frame->endTime) / 2; + auto start = frame->startTime; + auto end = frame->endTime; + // 二分查找 + while (start <= end) { + auto currentValue = static_cast(property->getValueAt(current)); + if (currentValue > value) { + end = current - 1; + } else if (currentValue < value) { + start = current + 1; + } else { + break; + } + current = (start + end) / 2; } - current = (start + end) / 2; - } - return current; + return current; } Frame PAGImageLayer::getFrameFromTimeRemap(pag::Frame value) { - auto timeRemap = getContentTimeRemap(); - if (!timeRemap->animatable()) { - return 0; - } - Frame result = 0; - auto property = static_cast*>(timeRemap); - for (auto frame : property->keyframes) { - if (frame->startValue > value) { - break; - } else if (frame->endValue <= value) { - result = frame->endTime; - } else { - switch (frame->interpolationType) { - case pag::KeyframeInterpolationType::Linear: { - auto scale = - (frame->endTime - frame->startTime) * 1.0 / (frame->endValue - frame->startValue); - result = frame->startTime + ceil((value - frame->startValue) * scale); - } break; - case pag::KeyframeInterpolationType::Hold: - result = frame->endTime; - break; - case pag::KeyframeInterpolationType::Bezier: - result = GetFrameFromBezierTimeRemap(value, frame, property); - break; - default: - break; - } - break; - } - } - return result; + auto timeRemap = getContentTimeRemap(); + if (!timeRemap->animatable()) { + return 0; + } + Frame result = 0; + auto property = static_cast*>(timeRemap); + for (auto frame : property->keyframes) { + if (frame->startValue > value) { + break; + } else if (frame->endValue <= value) { + result = frame->endTime; + } else { + switch (frame->interpolationType) { + case pag::KeyframeInterpolationType::Linear: { + auto scale = + (frame->endTime - frame->startTime) * 1.0 / (frame->endValue - frame->startValue); + result = frame->startTime + ceil((value - frame->startValue) * scale); + } + break; + case pag::KeyframeInterpolationType::Hold: + result = frame->endTime; + break; + case pag::KeyframeInterpolationType::Bezier: + result = GetFrameFromBezierTimeRemap(value, frame, property); + break; + default: + break; + } + break; + } + } + return result; } // ImageBytesV3场景下,图片的透明区域会发生裁剪,不能从图片解码中获取宽高 void PAGImageLayer::measureBounds(Rect* bounds) { - auto imageLayer = static_cast(layer); - bounds->setWH(imageLayer->imageBytes->width, imageLayer->imageBytes->height); + auto imageLayer = static_cast(layer); + bounds->setWH(imageLayer->imageBytes->width, imageLayer->imageBytes->height); } } // namespace pag diff --git a/src/rendering/layers/PAGLayer.cpp b/src/rendering/layers/PAGLayer.cpp index 0696205471..026f59dc42 100644 --- a/src/rendering/layers/PAGLayer.cpp +++ b/src/rendering/layers/PAGLayer.cpp @@ -30,538 +30,538 @@ namespace pag { PAGLayer::PAGLayer(std::shared_ptr file, Layer* layer) : layer(layer), file(std::move(file)), _uniqueID(UniqueID::Next()) { - layerMatrix.setIdentity(); - if (layer != nullptr) { // could be nullptr. - layerCache = LayerCache::Get(layer); - layerVisible = layer->isActive; - startFrame = layer->startTime; - } + layerMatrix.setIdentity(); + if (layer != nullptr) { // could be nullptr. + layerCache = LayerCache::Get(layer); + layerVisible = layer->isActive; + startFrame = layer->startTime; + } } PAGLayer::~PAGLayer() { - if (_trackMatteLayer) { - _trackMatteLayer->detachFromTree(); - _trackMatteLayer->trackMatteOwner = nullptr; - } + if (_trackMatteLayer) { + _trackMatteLayer->detachFromTree(); + _trackMatteLayer->trackMatteOwner = nullptr; + } } uint32_t PAGLayer::uniqueID() const { - return _uniqueID; + return _uniqueID; } LayerType PAGLayer::layerType() const { - return layer->type(); + return layer->type(); } std::string PAGLayer::layerName() const { - return layer->name; + return layer->name; } Matrix PAGLayer::matrix() const { - LockGuard autoLock(rootLocker); - return layerMatrix; + LockGuard autoLock(rootLocker); + return layerMatrix; } void PAGLayer::setMatrix(const Matrix& value) { - LockGuard autoLock(rootLocker); - setMatrixInternal(value); + LockGuard autoLock(rootLocker); + setMatrixInternal(value); } void PAGLayer::resetMatrix() { - LockGuard autoLock(rootLocker); - setMatrixInternal(Matrix::I()); + LockGuard autoLock(rootLocker); + setMatrixInternal(Matrix::I()); } Matrix PAGLayer::getTotalMatrix() { - LockGuard autoLock(rootLocker); - return getTotalMatrixInternal(); + LockGuard autoLock(rootLocker); + return getTotalMatrixInternal(); } Matrix PAGLayer::getTotalMatrixInternal() { - auto matrix = layerCache->getTransform(contentFrame)->matrix; - matrix.postConcat(layerMatrix); - return matrix; + auto matrix = layerCache->getTransform(contentFrame)->matrix; + matrix.postConcat(layerMatrix); + return matrix; } void PAGLayer::setOpacity(const Opacity& value) { - LockGuard autoLock(rootLocker); - setOpacityInternal(value); + LockGuard autoLock(rootLocker); + setOpacityInternal(value); } Opacity PAGLayer::opacity() const { - LockGuard autoLock(rootLocker); - return layerOpacity; + LockGuard autoLock(rootLocker); + return layerOpacity; } bool PAGLayer::visible() const { - LockGuard autoLock(rootLocker); - return layerVisible; + LockGuard autoLock(rootLocker); + return layerVisible; } void PAGLayer::setVisible(bool value) { - LockGuard autoLock(rootLocker); - setVisibleInternal(value); + LockGuard autoLock(rootLocker); + setVisibleInternal(value); } void PAGLayer::setVisibleInternal(bool value) { - if (value == layerVisible) { - return; - } - layerVisible = value; - notifyModified(); + if (value == layerVisible) { + return; + } + layerVisible = value; + notifyModified(); } Rect PAGLayer::getBounds() { - LockGuard autoLock(rootLocker); - Rect bounds = {}; - measureBounds(&bounds); - return bounds; + LockGuard autoLock(rootLocker); + Rect bounds = {}; + measureBounds(&bounds); + return bounds; } int PAGLayer::editableIndex() const { - return _editableIndex; + return _editableIndex; } std::shared_ptr PAGLayer::parent() const { - LockGuard autoLock(rootLocker); - if (_parent) { - return std::static_pointer_cast(_parent->weakThis.lock()); - } - return nullptr; + LockGuard autoLock(rootLocker); + if (_parent) { + return std::static_pointer_cast(_parent->weakThis.lock()); + } + return nullptr; } std::vector PAGLayer::markers() const { - std::vector result = {}; - for (auto marker : layer->markers) { - result.push_back(marker); - } - return result; + std::vector result = {}; + for (auto marker : layer->markers) { + result.push_back(marker); + } + return result; } int64_t PAGLayer::localTimeToGlobal(int64_t localTime) const { - LockGuard autoLock(rootLocker); - auto localFrame = TimeToFrame(localTime, frameRateInternal()); - auto globalFrame = localFrameToGlobal(localFrame); - auto globalLayer = this; - while (globalLayer) { - auto owner = globalLayer->getTimelineOwner(); - if (!owner) { - break; + LockGuard autoLock(rootLocker); + auto localFrame = TimeToFrame(localTime, frameRateInternal()); + auto globalFrame = localFrameToGlobal(localFrame); + auto globalLayer = this; + while (globalLayer) { + auto owner = globalLayer->getTimelineOwner(); + if (!owner) { + break; + } + globalLayer = owner; } - globalLayer = owner; - } - return FrameToTime(globalFrame, globalLayer->frameRateInternal()); + return FrameToTime(globalFrame, globalLayer->frameRateInternal()); } Frame PAGLayer::localFrameToGlobal(Frame localFrame) const { - auto parent = getTimelineOwner(); - auto childFrameRate = frameRateInternal(); - while (parent) { - localFrame = parent->childFrameToLocal(localFrame, childFrameRate); - childFrameRate = parent->frameRateInternal(); - parent = parent->getTimelineOwner(); - } - return localFrame; + auto parent = getTimelineOwner(); + auto childFrameRate = frameRateInternal(); + while (parent) { + localFrame = parent->childFrameToLocal(localFrame, childFrameRate); + childFrameRate = parent->frameRateInternal(); + parent = parent->getTimelineOwner(); + } + return localFrame; } int64_t PAGLayer::globalToLocalTime(int64_t globalTime) const { - LockGuard autoLock(rootLocker); - auto globalLayer = this; - while (globalLayer) { - auto owner = globalLayer->getTimelineOwner(); - if (!owner) { - break; + LockGuard autoLock(rootLocker); + auto globalLayer = this; + while (globalLayer) { + auto owner = globalLayer->getTimelineOwner(); + if (!owner) { + break; + } + globalLayer = owner; } - globalLayer = owner; - } - auto globalFrame = TimeToFrame(globalTime, globalLayer->frameRateInternal()); - auto localFrame = globalToLocalFrame(globalFrame); - return FrameToTime(localFrame, frameRateInternal()); + auto globalFrame = TimeToFrame(globalTime, globalLayer->frameRateInternal()); + auto localFrame = globalToLocalFrame(globalFrame); + return FrameToTime(localFrame, frameRateInternal()); } Frame PAGLayer::globalToLocalFrame(Frame globalFrame) const { - std::vector list = {}; - auto owner = getTimelineOwner(); - while (owner) { - list.push_back(owner); - owner = owner->getTimelineOwner(); - } - for (int i = static_cast(list.size() - 1); i >= 0; i--) { - auto childFrameRate = i > 0 ? list[i - 1]->frameRateInternal() : frameRateInternal(); - globalFrame = list[i]->localFrameToChild(globalFrame, childFrameRate); - } - return globalFrame; + std::vector list = {}; + auto owner = getTimelineOwner(); + while (owner) { + list.push_back(owner); + owner = owner->getTimelineOwner(); + } + for (int i = static_cast(list.size() - 1); i >= 0; i--) { + auto childFrameRate = i > 0 ? list[i - 1]->frameRateInternal() : frameRateInternal(); + globalFrame = list[i]->localFrameToChild(globalFrame, childFrameRate); + } + return globalFrame; } Frame PAGLayer::localFrameToChild(Frame localFrame, float childFrameRate) const { - auto timeScale = childFrameRate / frameRateInternal(); - return static_cast(roundf((localFrame - startFrame) * timeScale)); + auto timeScale = childFrameRate / frameRateInternal(); + return static_cast(roundf((localFrame - startFrame) * timeScale)); } Frame PAGLayer::childFrameToLocal(Frame childFrame, float childFrameRate) const { - auto timeScale = frameRateInternal() / childFrameRate; - return static_cast(roundf(childFrame * timeScale)) + startFrame; + auto timeScale = frameRateInternal() / childFrameRate; + return static_cast(roundf(childFrame * timeScale)) + startFrame; } PAGLayer* PAGLayer::getTimelineOwner() const { - if (_parent) { - return _parent; - } - if (trackMatteOwner) { - return trackMatteOwner->_parent; - } - return nullptr; + if (_parent) { + return _parent; + } + if (trackMatteOwner) { + return trackMatteOwner->_parent; + } + return nullptr; } int64_t PAGLayer::startTime() const { - LockGuard autoLock(rootLocker); - return startTimeInternal(); + LockGuard autoLock(rootLocker); + return startTimeInternal(); } int64_t PAGLayer::startTimeInternal() const { - return FrameToTime(startFrame, frameRateInternal()); + return FrameToTime(startFrame, frameRateInternal()); } void PAGLayer::setStartTime(int64_t time) { - LockGuard autoLock(rootLocker); - setStartTimeInternal(time); + LockGuard autoLock(rootLocker); + setStartTimeInternal(time); } void PAGLayer::setStartTimeInternal(int64_t time) { - auto targetStartFrame = TimeToFrame(time, frameRateInternal()); - if (startFrame == targetStartFrame) { - return; - } - auto layerFrame = startFrame + contentFrame; - startFrame = targetStartFrame; - if (_parent && _parent->emptyComposition) { - _parent->updateDurationAndFrameRate(); - } - gotoTimeAndNotifyChanged(FrameToTime(layerFrame, frameRateInternal())); - onTimelineChanged(); + auto targetStartFrame = TimeToFrame(time, frameRateInternal()); + if (startFrame == targetStartFrame) { + return; + } + auto layerFrame = startFrame + contentFrame; + startFrame = targetStartFrame; + if (_parent && _parent->emptyComposition) { + _parent->updateDurationAndFrameRate(); + } + gotoTimeAndNotifyChanged(FrameToTime(layerFrame, frameRateInternal())); + onTimelineChanged(); } int64_t PAGLayer::duration() const { - LockGuard autoLock(rootLocker); - return durationInternal(); + LockGuard autoLock(rootLocker); + return durationInternal(); } int64_t PAGLayer::durationInternal() const { - return FrameToTime(stretchedFrameDuration(), frameRateInternal()); + return FrameToTime(stretchedFrameDuration(), frameRateInternal()); } float PAGLayer::frameRate() const { - LockGuard autoLock(rootLocker); - return frameRateInternal(); + LockGuard autoLock(rootLocker); + return frameRateInternal(); } float PAGLayer::frameRateInternal() const { - return file ? file->frameRate() : 60; + return file ? file->frameRate() : 60; } int64_t PAGLayer::currentTime() const { - LockGuard autoLock(rootLocker); - return currentTimeInternal(); + LockGuard autoLock(rootLocker); + return currentTimeInternal(); } int64_t PAGLayer::currentTimeInternal() const { - return FrameToTime(currentFrameInternal(), frameRateInternal()); + return FrameToTime(currentFrameInternal(), frameRateInternal()); } void PAGLayer::setCurrentTime(int64_t time) { - LockGuard autoLock(rootLocker); - setCurrentTimeInternal(time); + LockGuard autoLock(rootLocker); + setCurrentTimeInternal(time); } bool PAGLayer::setCurrentTimeInternal(int64_t time) { - return gotoTimeAndNotifyChanged(time); + return gotoTimeAndNotifyChanged(time); } Frame PAGLayer::currentFrameInternal() const { - return startFrame + stretchedContentFrame(); + return startFrame + stretchedContentFrame(); } double PAGLayer::getProgress() { - LockGuard autoLock(rootLocker); - return getProgressInternal(); + LockGuard autoLock(rootLocker); + return getProgressInternal(); } double PAGLayer::getProgressInternal() { - return FrameToProgress(stretchedContentFrame(), stretchedFrameDuration()); + return FrameToProgress(stretchedContentFrame(), stretchedFrameDuration()); } void PAGLayer::setProgress(double percent) { - LockGuard autoLock(rootLocker); - setProgressInternal(percent); + LockGuard autoLock(rootLocker); + setProgressInternal(percent); } void PAGLayer::setProgressInternal(double percent) { - gotoTimeAndNotifyChanged(startTimeInternal() + ProgressToTime(percent, durationInternal())); + gotoTimeAndNotifyChanged(startTimeInternal() + ProgressToTime(percent, durationInternal())); } void PAGLayer::preFrame() { - LockGuard autoLock(rootLocker); - preFrameInternal(); + LockGuard autoLock(rootLocker); + preFrameInternal(); } void PAGLayer::preFrameInternal() { - auto totalFrames = stretchedFrameDuration(); - if (totalFrames <= 1) { - return; - } - auto targetContentFrame = stretchedContentFrame(); - targetContentFrame--; - if (targetContentFrame < 0) { - targetContentFrame = totalFrames - 1; - } - gotoTimeAndNotifyChanged(FrameToTime(startFrame + targetContentFrame, frameRateInternal())); + auto totalFrames = stretchedFrameDuration(); + if (totalFrames <= 1) { + return; + } + auto targetContentFrame = stretchedContentFrame(); + targetContentFrame--; + if (targetContentFrame < 0) { + targetContentFrame = totalFrames - 1; + } + gotoTimeAndNotifyChanged(FrameToTime(startFrame + targetContentFrame, frameRateInternal())); } void PAGLayer::nextFrame() { - LockGuard autoLock(rootLocker); - nextFrameInternal(); + LockGuard autoLock(rootLocker); + nextFrameInternal(); } void PAGLayer::nextFrameInternal() { - auto totalFrames = stretchedFrameDuration(); - if (totalFrames <= 1) { - return; - } - auto targetContentFrame = stretchedContentFrame(); - targetContentFrame++; - if (targetContentFrame >= totalFrames) { - targetContentFrame = 0; - } - gotoTimeAndNotifyChanged(FrameToTime(startFrame + targetContentFrame, frameRateInternal())); + auto totalFrames = stretchedFrameDuration(); + if (totalFrames <= 1) { + return; + } + auto targetContentFrame = stretchedContentFrame(); + targetContentFrame++; + if (targetContentFrame >= totalFrames) { + targetContentFrame = 0; + } + gotoTimeAndNotifyChanged(FrameToTime(startFrame + targetContentFrame, frameRateInternal())); } Frame PAGLayer::frameDuration() const { - return layer->duration; + return layer->duration; } Frame PAGLayer::stretchedFrameDuration() const { - return frameDuration(); + return frameDuration(); } Frame PAGLayer::stretchedContentFrame() const { - return contentFrame; + return contentFrame; } bool PAGLayer::gotoTimeAndNotifyChanged(int64_t targetTime) { - auto changed = gotoTime(targetTime); - if (changed) { - notifyModified(); - } - return changed; + auto changed = gotoTime(targetTime); + if (changed) { + notifyModified(); + } + return changed; } std::shared_ptr PAGLayer::trackMatteLayer() const { - return _trackMatteLayer; + return _trackMatteLayer; } Point PAGLayer::globalToLocalPoint(float stageX, float stageY) { - Matrix totalMatrix = Matrix::I(); - auto pagLayer = this; - while (pagLayer) { - auto matrix = pagLayer->getTotalMatrixInternal(); - totalMatrix.postConcat(matrix); - pagLayer = pagLayer->_parent; - } - Point localPoint = {stageX, stageY}; - MapPointInverted(totalMatrix, &localPoint); - return localPoint; + Matrix totalMatrix = Matrix::I(); + auto pagLayer = this; + while (pagLayer) { + auto matrix = pagLayer->getTotalMatrixInternal(); + totalMatrix.postConcat(matrix); + pagLayer = pagLayer->_parent; + } + Point localPoint = {stageX, stageY}; + MapPointInverted(totalMatrix, &localPoint); + return localPoint; } bool PAGLayer::excludedFromTimeline() const { - LockGuard autoLock(rootLocker); - return _excludedFromTimeline; + LockGuard autoLock(rootLocker); + return _excludedFromTimeline; } void PAGLayer::setExcludedFromTimeline(bool value) { - LockGuard autoLock(rootLocker); - _excludedFromTimeline = value; + LockGuard autoLock(rootLocker); + _excludedFromTimeline = value; } void PAGLayer::notifyModified(bool contentChanged) { - if (contentChanged) { - contentVersion++; - } - auto parentLayer = getParentOrOwner(); - while (parentLayer) { - parentLayer->contentVersion++; - parentLayer = parentLayer->getParentOrOwner(); - } + if (contentChanged) { + contentVersion++; + } + auto parentLayer = getParentOrOwner(); + while (parentLayer) { + parentLayer->contentVersion++; + parentLayer = parentLayer->getParentOrOwner(); + } } PAGLayer* PAGLayer::getParentOrOwner() const { - if (_parent) { - return _parent; - } - if (trackMatteOwner) { - return trackMatteOwner; - } - return nullptr; + if (_parent) { + return _parent; + } + if (trackMatteOwner) { + return trackMatteOwner; + } + return nullptr; } bool PAGLayer::contentModified() const { - return contentVersion > 0; + return contentVersion > 0; } bool PAGLayer::cacheFilters() const { - return layerCache->cacheFilters(); + return layerCache->cacheFilters(); } const Layer* PAGLayer::getLayer() const { - return layer; + return layer; } const PAGStage* PAGLayer::getStage() const { - return stage; + return stage; } bool PAGLayer::gotoTime(int64_t layerTime) { - auto changed = false; - if (_trackMatteLayer != nullptr) { - changed = _trackMatteLayer->gotoTime(layerTime); - } - auto layerFrame = TimeToFrame(layerTime, frameRateInternal()); - auto oldContentFrame = contentFrame; - contentFrame = layerFrame - startFrame; - if (!changed) { - changed = layerCache->checkFrameChanged(contentFrame, oldContentFrame); - } - return changed; + auto changed = false; + if (_trackMatteLayer != nullptr) { + changed = _trackMatteLayer->gotoTime(layerTime); + } + auto layerFrame = TimeToFrame(layerTime, frameRateInternal()); + auto oldContentFrame = contentFrame; + contentFrame = layerFrame - startFrame; + if (!changed) { + changed = layerCache->checkFrameChanged(contentFrame, oldContentFrame); + } + return changed; } void PAGLayer::draw(Recorder* recorder) { - getContent()->draw(recorder); + getContent()->draw(recorder); } void PAGLayer::measureBounds(Rect* bounds) { - getContent()->measureBounds(bounds); + getContent()->measureBounds(bounds); } bool PAGLayer::isPAGFile() const { - return false; + return false; } Content* PAGLayer::getContent() { - return layerCache->getContent(contentFrame); + return layerCache->getContent(contentFrame); } void PAGLayer::invalidateCacheScale() { - if (stage) { - stage->invalidateCacheScale(this); - } + if (stage) { + stage->invalidateCacheScale(this); + } } void PAGLayer::onAddToStage(PAGStage* pagStage) { - stage = pagStage; - pagStage->addReference(this); - if (_trackMatteLayer != nullptr) { - _trackMatteLayer->onAddToStage(pagStage); - } + stage = pagStage; + pagStage->addReference(this); + if (_trackMatteLayer != nullptr) { + _trackMatteLayer->onAddToStage(pagStage); + } } void PAGLayer::onRemoveFromStage() { - stage->removeReference(this); - stage = nullptr; - if (_trackMatteLayer != nullptr) { - _trackMatteLayer->onRemoveFromStage(); - } + stage->removeReference(this); + stage = nullptr; + if (_trackMatteLayer != nullptr) { + _trackMatteLayer->onRemoveFromStage(); + } } void PAGLayer::onAddToRootFile(PAGFile* pagFile) { - if (_trackMatteLayer != nullptr && _trackMatteLayer->file == file) { - _trackMatteLayer->onAddToRootFile(pagFile); - } - rootFile = pagFile; + if (_trackMatteLayer != nullptr && _trackMatteLayer->file == file) { + _trackMatteLayer->onAddToRootFile(pagFile); + } + rootFile = pagFile; } void PAGLayer::onRemoveFromRootFile() { - if (_trackMatteLayer != nullptr && _trackMatteLayer->file == file) { - _trackMatteLayer->onRemoveFromRootFile(); - } - rootFile = nullptr; + if (_trackMatteLayer != nullptr && _trackMatteLayer->file == file) { + _trackMatteLayer->onRemoveFromRootFile(); + } + rootFile = nullptr; } void PAGLayer::onTimelineChanged() { } void PAGLayer::updateRootLocker(std::shared_ptr newLocker) { - if (_trackMatteLayer != nullptr) { - _trackMatteLayer->updateRootLocker(newLocker); - } - rootLocker = newLocker; + if (_trackMatteLayer != nullptr) { + _trackMatteLayer->updateRootLocker(newLocker); + } + rootLocker = newLocker; } void PAGLayer::setMatrixInternal(const Matrix& matrix) { - if (matrix == layerMatrix) { - return; - } - layerMatrix = matrix; - notifyModified(); - invalidateCacheScale(); + if (matrix == layerMatrix) { + return; + } + layerMatrix = matrix; + notifyModified(); + invalidateCacheScale(); } void PAGLayer::setOpacityInternal(const Opacity& opacity) { - if (opacity == layerOpacity) { - return; - } - layerOpacity = opacity; - notifyModified(); + if (opacity == layerOpacity) { + return; + } + layerOpacity = opacity; + notifyModified(); } void PAGLayer::removeFromParentOrOwner() { - if (_parent) { - auto oldIndex = _parent->getLayerIndexInternal(weakThis.lock()); - if (oldIndex >= 0) { - _parent->doRemoveLayer(oldIndex); + if (_parent) { + auto oldIndex = _parent->getLayerIndexInternal(weakThis.lock()); + if (oldIndex >= 0) { + _parent->doRemoveLayer(oldIndex); + } + } + if (trackMatteOwner) { + detachFromTree(); + trackMatteOwner->_trackMatteLayer = nullptr; + trackMatteOwner = nullptr; } - } - if (trackMatteOwner) { - detachFromTree(); - trackMatteOwner->_trackMatteLayer = nullptr; - trackMatteOwner = nullptr; - } } void PAGLayer::attachToTree(std::shared_ptr newLocker, PAGStage* newStage) { - updateRootLocker(newLocker); - if (newStage) { - onAddToStage(newStage); - } + updateRootLocker(newLocker); + if (newStage) { + onAddToStage(newStage); + } } void PAGLayer::detachFromTree() { - if (stage) { - onRemoveFromStage(); - } - auto locker = std::make_shared(); - updateRootLocker(locker); + if (stage) { + onRemoveFromStage(); + } + auto locker = std::make_shared(); + updateRootLocker(locker); } bool PAGLayer::getTransform(Transform* transform) { - if (contentFrame < 0 || contentFrame >= frameDuration() || !layerMatrix.invertible() || - layerOpacity == Transparent) { - return false; - } - auto layerTransform = layerCache->getTransform(contentFrame); - if (!layerTransform->visible()) { - return false; - } - *transform = *layerTransform; - transform->matrix.postConcat(layerMatrix); - transform->opacity = OpacityConcat(transform->opacity, layerOpacity); - return true; + if (contentFrame < 0 || contentFrame >= frameDuration() || !layerMatrix.invertible() || + layerOpacity == Transparent) { + return false; + } + auto layerTransform = layerCache->getTransform(contentFrame); + if (!layerTransform->visible()) { + return false; + } + *transform = *layerTransform; + transform->matrix.postConcat(layerMatrix); + transform->opacity = OpacityConcat(transform->opacity, layerOpacity); + return true; } std::shared_ptr PAGLayer::getFile() const { - return file; + return file; } bool PAGLayer::frameVisible() const { - return contentFrame >= 0 && contentFrame < frameDuration(); + return contentFrame >= 0 && contentFrame < frameDuration(); } } // namespace pag diff --git a/src/rendering/layers/PAGSolidLayer.cpp b/src/rendering/layers/PAGSolidLayer.cpp index 60d6d2c314..af9067e238 100644 --- a/src/rendering/layers/PAGSolidLayer.cpp +++ b/src/rendering/layers/PAGSolidLayer.cpp @@ -25,24 +25,24 @@ namespace pag { std::shared_ptr PAGSolidLayer::Make(int64_t duration, int32_t width, int32_t height, - Color solidColor, Opacity opacity) { - if (width <= 0 || height <= 0) { - return nullptr; - } + Color solidColor, Opacity opacity) { + if (width <= 0 || height <= 0) { + return nullptr; + } - auto layer = new SolidLayer(); - auto transform = Transform2D::MakeDefault(); - transform->opacity->value = opacity; - layer->transform = transform; - layer->width = width; - layer->height = height; - layer->solidColor = solidColor; - layer->duration = TimeToFrame(duration, 60); + auto layer = new SolidLayer(); + auto transform = Transform2D::MakeDefault(); + transform->opacity->value = opacity; + layer->transform = transform; + layer->width = width; + layer->height = height; + layer->solidColor = solidColor; + layer->duration = TimeToFrame(duration, 60); - auto pagSolidLayer = std::make_shared(nullptr, layer); - pagSolidLayer->emptySolidLayer = layer; - pagSolidLayer->weakThis = pagSolidLayer; - return pagSolidLayer; + auto pagSolidLayer = std::make_shared(nullptr, layer); + pagSolidLayer->emptySolidLayer = layer; + pagSolidLayer->weakThis = pagSolidLayer; + return pagSolidLayer; } PAGSolidLayer::PAGSolidLayer(std::shared_ptr file, SolidLayer* layer) @@ -50,45 +50,45 @@ PAGSolidLayer::PAGSolidLayer(std::shared_ptr file, SolidLayer* layer) } PAGSolidLayer::~PAGSolidLayer() { - delete replacement; - delete emptySolidLayer; + delete replacement; + delete emptySolidLayer; } Content* PAGSolidLayer::getContent() { - if (replacement != nullptr) { - return replacement; - } - return layerCache->getContent(contentFrame); + if (replacement != nullptr) { + return replacement; + } + return layerCache->getContent(contentFrame); } bool PAGSolidLayer::contentModified() const { - return replacement != nullptr; + return replacement != nullptr; } Color PAGSolidLayer::solidColor() { - LockGuard autoLock(rootLocker); - return _solidColor; + LockGuard autoLock(rootLocker); + return _solidColor; } void PAGSolidLayer::setSolidColor(const pag::Color& value) { - LockGuard autoLock(rootLocker); - if (_solidColor == value) { - return; - } - _solidColor = value; - if (replacement != nullptr) { - delete replacement; - replacement = nullptr; - } - auto solidLayer = static_cast(layer); - if (solidLayer->solidColor != _solidColor) { - Path path = {}; - path.addRect(0, 0, solidLayer->width, solidLayer->height); - auto solid = Shape::MakeFrom(path, _solidColor); - replacement = new GraphicContent(solid); - } - notifyModified(true); - invalidateCacheScale(); + LockGuard autoLock(rootLocker); + if (_solidColor == value) { + return; + } + _solidColor = value; + if (replacement != nullptr) { + delete replacement; + replacement = nullptr; + } + auto solidLayer = static_cast(layer); + if (solidLayer->solidColor != _solidColor) { + Path path = {}; + path.addRect(0, 0, solidLayer->width, solidLayer->height); + auto solid = Shape::MakeFrom(path, _solidColor); + replacement = new GraphicContent(solid); + } + notifyModified(true); + invalidateCacheScale(); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/layers/PAGStage.cpp b/src/rendering/layers/PAGStage.cpp index 108372019c..eae0337968 100644 --- a/src/rendering/layers/PAGStage.cpp +++ b/src/rendering/layers/PAGStage.cpp @@ -30,343 +30,343 @@ namespace pag { std::shared_ptr PAGStage::Make(int width, int height) { - auto stage = std::shared_ptr(new PAGStage(width, height)); - stage->weakThis = stage; - return stage; + auto stage = std::shared_ptr(new PAGStage(width, height)); + stage->weakThis = stage; + return stage; } PAGStage::PAGStage(int width, int height) : PAGComposition(width, height) { - rootLocker = std::make_shared(); - stage = this; + rootLocker = std::make_shared(); + stage = this; } PAGStage::~PAGStage() { - // 需要提前调用 removeAllLayers(), - // 否则父类析构时再调用会依赖 stage 的相关属性, - // 此时 stage 已经销毁. - removeAllLayers(); + // 需要提前调用 removeAllLayers(), + // 否则父类析构时再调用会依赖 stage 的相关属性, + // 此时 stage 已经销毁. + removeAllLayers(); } void PAGStage::setCacheScale(float value) { - if (value <= 0 || value > 1.0f) { - value = 1.0f; - } - _cacheScale = value; + if (value <= 0 || value > 1.0f) { + value = 1.0f; + } + _cacheScale = value; } std::shared_ptr PAGStage::getRootComposition() { - if (layers.empty()) { - return nullptr; - } - auto layer = layers.front(); - if (layer->layerType() != LayerType::PreCompose) { - return nullptr; - } - return std::static_pointer_cast(layer); + if (layers.empty()) { + return nullptr; + } + auto layer = layers.front(); + if (layer->layerType() != LayerType::PreCompose) { + return nullptr; + } + return std::static_pointer_cast(layer); } uint32_t PAGStage::getContentVersion() const { - return contentVersion; + return contentVersion; } std::shared_ptr PAGStage::getSequenceFile(Sequence* sequence) { - if (sequence == nullptr) { - return nullptr; - } - auto result = layerReferenceMap.find(sequence->composition->uniqueID); - if (result == layerReferenceMap.end()) { - return nullptr; - } - return result->second.front()->getFile(); + if (sequence == nullptr) { + return nullptr; + } + auto result = layerReferenceMap.find(sequence->composition->uniqueID); + if (result == layerReferenceMap.end()) { + return nullptr; + } + return result->second.front()->getFile(); } void PAGStage::addReference(PAGLayer* pagLayer) { - addToReferenceMap(pagLayer->uniqueID(), pagLayer); - addToReferenceMap(pagLayer->layer->uniqueID, pagLayer); - if (pagLayer->layerType() == LayerType::PreCompose) { - auto composition = static_cast(pagLayer->layer)->composition; - addToReferenceMap(composition->uniqueID, pagLayer); - } else if (pagLayer->layerType() == LayerType::Image) { - auto imageBytes = static_cast(pagLayer->layer)->imageBytes; - addToReferenceMap(imageBytes->uniqueID, pagLayer); - auto pagImage = static_cast(pagLayer)->getPAGImage(); - if (pagImage != nullptr) { - addReference(pagImage.get(), pagLayer); - } - } - auto targetLayer = pagLayer->layer; - for (auto& style : targetLayer->layerStyles) { - addToReferenceMap(style->uniqueID, pagLayer); - } - for (auto& effect : targetLayer->effects) { - addToReferenceMap(effect->uniqueID, pagLayer); - } - invalidateCacheScale(pagLayer); + addToReferenceMap(pagLayer->uniqueID(), pagLayer); + addToReferenceMap(pagLayer->layer->uniqueID, pagLayer); + if (pagLayer->layerType() == LayerType::PreCompose) { + auto composition = static_cast(pagLayer->layer)->composition; + addToReferenceMap(composition->uniqueID, pagLayer); + } else if (pagLayer->layerType() == LayerType::Image) { + auto imageBytes = static_cast(pagLayer->layer)->imageBytes; + addToReferenceMap(imageBytes->uniqueID, pagLayer); + auto pagImage = static_cast(pagLayer)->getPAGImage(); + if (pagImage != nullptr) { + addReference(pagImage.get(), pagLayer); + } + } + auto targetLayer = pagLayer->layer; + for (auto& style : targetLayer->layerStyles) { + addToReferenceMap(style->uniqueID, pagLayer); + } + for (auto& effect : targetLayer->effects) { + addToReferenceMap(effect->uniqueID, pagLayer); + } + invalidateCacheScale(pagLayer); } void PAGStage::addToReferenceMap(ID uniqueID, PAGLayer* pagLayer) { - auto& layers = layerReferenceMap[uniqueID]; - auto position = std::find(layers.begin(), layers.end(), pagLayer); - if (position == layers.end()) { - layers.push_back(pagLayer); - } + auto& layers = layerReferenceMap[uniqueID]; + auto position = std::find(layers.begin(), layers.end(), pagLayer); + if (position == layers.end()) { + layers.push_back(pagLayer); + } } void PAGStage::removeReference(PAGLayer* pagLayer) { - // 重置 rootVersion,防止 rootComposition 被移除又加入一个 version 相同的其他 Composition。 - rootVersion = -1; - removeFromReferenceMap(pagLayer->uniqueID(), pagLayer); - removeFromReferenceMap(pagLayer->layer->uniqueID, pagLayer); - if (pagLayer->layerType() == LayerType::PreCompose) { - auto composition = static_cast(pagLayer->layer)->composition; - auto empty = removeFromReferenceMap(composition->uniqueID, pagLayer); - if (empty) { - sequenceCache.erase(composition->uniqueID); - } - } else if (pagLayer->layerType() == LayerType::Image) { - auto imageBytes = static_cast(pagLayer->layer)->imageBytes; - removeFromReferenceMap(imageBytes->uniqueID, pagLayer); - auto pagImage = static_cast(pagLayer)->getPAGImage(); - if (pagImage != nullptr) { - removeReference(pagImage.get(), pagLayer); - } - } - auto targetLayer = pagLayer->layer; - for (auto& style : targetLayer->layerStyles) { - removeFromReferenceMap(style->uniqueID, pagLayer); - } - for (auto& effect : targetLayer->effects) { - removeFromReferenceMap(effect->uniqueID, pagLayer); - } - invalidateCacheScale(pagLayer); + // 重置 rootVersion,防止 rootComposition 被移除又加入一个 version 相同的其他 Composition。 + rootVersion = -1; + removeFromReferenceMap(pagLayer->uniqueID(), pagLayer); + removeFromReferenceMap(pagLayer->layer->uniqueID, pagLayer); + if (pagLayer->layerType() == LayerType::PreCompose) { + auto composition = static_cast(pagLayer->layer)->composition; + auto empty = removeFromReferenceMap(composition->uniqueID, pagLayer); + if (empty) { + sequenceCache.erase(composition->uniqueID); + } + } else if (pagLayer->layerType() == LayerType::Image) { + auto imageBytes = static_cast(pagLayer->layer)->imageBytes; + removeFromReferenceMap(imageBytes->uniqueID, pagLayer); + auto pagImage = static_cast(pagLayer)->getPAGImage(); + if (pagImage != nullptr) { + removeReference(pagImage.get(), pagLayer); + } + } + auto targetLayer = pagLayer->layer; + for (auto& style : targetLayer->layerStyles) { + removeFromReferenceMap(style->uniqueID, pagLayer); + } + for (auto& effect : targetLayer->effects) { + removeFromReferenceMap(effect->uniqueID, pagLayer); + } + invalidateCacheScale(pagLayer); } bool PAGStage::removeFromReferenceMap(ID uniqueID, PAGLayer* pagLayer) { - auto result = layerReferenceMap.find(uniqueID); - if (result == layerReferenceMap.end()) { - return true; - } - auto& layers = result->second; - auto position = std::find(layers.begin(), layers.end(), pagLayer); - if (position == layers.end()) { - return false; - } - auto empty = layers.size() == 1; - if (empty) { - layerReferenceMap.erase(result); - invalidAssets.insert(uniqueID); - } else { - layers.erase(position); - } - return empty; + auto result = layerReferenceMap.find(uniqueID); + if (result == layerReferenceMap.end()) { + return true; + } + auto& layers = result->second; + auto position = std::find(layers.begin(), layers.end(), pagLayer); + if (position == layers.end()) { + return false; + } + auto empty = layers.size() == 1; + if (empty) { + layerReferenceMap.erase(result); + invalidAssets.insert(uniqueID); + } else { + layers.erase(position); + } + return empty; } void PAGStage::addReference(PAGImage* pagImage, pag::PAGLayer* pagLayer) { - addToReferenceMap(pagImage->uniqueID(), pagLayer); - pagImageMap[pagImage->uniqueID()] = pagImage; + addToReferenceMap(pagImage->uniqueID(), pagLayer); + pagImageMap[pagImage->uniqueID()] = pagImage; } void PAGStage::removeReference(PAGImage* pagImage, pag::PAGLayer* pagLayer) { - auto empty = removeFromReferenceMap(pagImage->uniqueID(), pagLayer); - if (empty) { - pagImageMap.erase(pagImage->uniqueID()); - } + auto empty = removeFromReferenceMap(pagImage->uniqueID(), pagLayer); + if (empty) { + pagImageMap.erase(pagImage->uniqueID()); + } } void PAGStage::invalidateCacheScale(PAGLayer* pagLayer) { - std::vector invalidIDs = {}; - invalidIDs.push_back(pagLayer->uniqueID()); - invalidIDs.push_back(pagLayer->layer->uniqueID); - if (pagLayer->layerType() == LayerType::PreCompose) { - auto composition = static_cast(pagLayer->layer)->composition; - invalidIDs.push_back(composition->uniqueID); - } else if (pagLayer->layerType() == LayerType::Image) { - auto imageBytes = static_cast(pagLayer->layer)->imageBytes; - invalidIDs.push_back(imageBytes->uniqueID); - auto pagImage = static_cast(pagLayer)->getPAGImage(); - if (pagImage != nullptr) { - invalidIDs.push_back(pagImage->uniqueID()); - } - } - for (auto id : invalidIDs) { - scaleFactorCache.erase(id); - } + std::vector invalidIDs = {}; + invalidIDs.push_back(pagLayer->uniqueID()); + invalidIDs.push_back(pagLayer->layer->uniqueID); + if (pagLayer->layerType() == LayerType::PreCompose) { + auto composition = static_cast(pagLayer->layer)->composition; + invalidIDs.push_back(composition->uniqueID); + } else if (pagLayer->layerType() == LayerType::Image) { + auto imageBytes = static_cast(pagLayer->layer)->imageBytes; + invalidIDs.push_back(imageBytes->uniqueID); + auto pagImage = static_cast(pagLayer)->getPAGImage(); + if (pagImage != nullptr) { + invalidIDs.push_back(pagImage->uniqueID()); + } + } + for (auto id : invalidIDs) { + scaleFactorCache.erase(id); + } } std::shared_ptr PAGStage::getSequenceGraphic(Composition* composition, - Frame compositionFrame) { - auto result = sequenceCache.find(composition->id); - if (result != sequenceCache.end()) { - if (result->second.compositionFrame == compositionFrame) { - return result->second.graphic; - } - sequenceCache.erase(result); - } - SequenceCache cache = {}; - cache.graphic = RenderSequenceComposition(composition, compositionFrame); - cache.compositionFrame = compositionFrame; - sequenceCache[composition->uniqueID] = cache; - return cache.graphic; + Frame compositionFrame) { + auto result = sequenceCache.find(composition->id); + if (result != sequenceCache.end()) { + if (result->second.compositionFrame == compositionFrame) { + return result->second.graphic; + } + sequenceCache.erase(result); + } + SequenceCache cache = {}; + cache.graphic = RenderSequenceComposition(composition, compositionFrame); + cache.compositionFrame = compositionFrame; + sequenceCache[composition->uniqueID] = cache; + return cache.graphic; } std::map> PAGStage::findNearlyVisibleLayersIn( - int64_t timeDistance) { - std::map> distanceMap = {}; - auto root = getRootComposition(); - if (root == nullptr) { +int64_t timeDistance) { + std::map> distanceMap = {}; + auto root = getRootComposition(); + if (root == nullptr) { + return distanceMap; + } + auto rootDuration = root->durationInternal(); + auto globalFrameRate = frameRateInternal(); + auto globalFrame = root->localFrameToGlobal(root->currentFrameInternal()); + auto globalCurrent = FrameToTime(globalFrame, globalFrameRate); + if (rootVersion != root->contentVersion) { + layerStartTimeMap = {}; + updateLayerStartTime(root.get()); + rootVersion = root->contentVersion; + } + for (auto& item : layerStartTimeMap) { + auto visibleStart = item.second; + if (globalCurrent > visibleStart) { + // 循环预测 + visibleStart += rootDuration; + } + auto distance = visibleStart - globalCurrent; + if (distance > 0 && distance <= timeDistance) { + distanceMap[distance].push_back(item.first); + } + } return distanceMap; - } - auto rootDuration = root->durationInternal(); - auto globalFrameRate = frameRateInternal(); - auto globalFrame = root->localFrameToGlobal(root->currentFrameInternal()); - auto globalCurrent = FrameToTime(globalFrame, globalFrameRate); - if (rootVersion != root->contentVersion) { - layerStartTimeMap = {}; - updateLayerStartTime(root.get()); - rootVersion = root->contentVersion; - } - for (auto& item : layerStartTimeMap) { - auto visibleStart = item.second; - if (globalCurrent > visibleStart) { - // 循环预测 - visibleStart += rootDuration; - } - auto distance = visibleStart - globalCurrent; - if (distance > 0 && distance <= timeDistance) { - distanceMap[distance].push_back(item.first); - } - } - return distanceMap; } void PAGStage::updateLayerStartTime(PAGLayer* pagLayer) { - if (pagLayer->layerType() == LayerType::PreCompose) { - updateChildLayerStartTime(static_cast(pagLayer)); - auto composition = static_cast(pagLayer->layer)->composition; - if (composition->type() != CompositionType::Video && - composition->type() != CompositionType::Bitmap) { - return; - } - } else if (pagLayer->layerType() != LayerType::Image) { - return; - } - auto frame = pagLayer->localFrameToGlobal(pagLayer->startFrame); - layerStartTimeMap[pagLayer] = FrameToTime(frame, frameRateInternal()); + if (pagLayer->layerType() == LayerType::PreCompose) { + updateChildLayerStartTime(static_cast(pagLayer)); + auto composition = static_cast(pagLayer->layer)->composition; + if (composition->type() != CompositionType::Video && + composition->type() != CompositionType::Bitmap) { + return; + } + } else if (pagLayer->layerType() != LayerType::Image) { + return; + } + auto frame = pagLayer->localFrameToGlobal(pagLayer->startFrame); + layerStartTimeMap[pagLayer] = FrameToTime(frame, frameRateInternal()); } void PAGStage::updateChildLayerStartTime(PAGComposition* pagComposition) { - for (auto& childLayer : pagComposition->layers) { - if (!childLayer->layerVisible || childLayer->_excludedFromTimeline) { - // 不可见和脱离时间轴的图层不需要预测。 - continue; + for (auto& childLayer : pagComposition->layers) { + if (!childLayer->layerVisible || childLayer->_excludedFromTimeline) { + // 不可见和脱离时间轴的图层不需要预测。 + continue; + } + updateLayerStartTime(childLayer.get()); } - updateLayerStartTime(childLayer.get()); - } } std::unordered_set PAGStage::getRemovedAssets() { - if (invalidAssets.empty()) { - return {}; - } - std::unordered_set removedAssets = {}; - for (auto id : invalidAssets) { - if (layerReferenceMap.count(id) == 0) { - removedAssets.insert(id); - } - } - invalidAssets = {}; - return removedAssets; + if (invalidAssets.empty()) { + return {}; + } + std::unordered_set removedAssets = {}; + for (auto id : invalidAssets) { + if (layerReferenceMap.count(id) == 0) { + removedAssets.insert(id); + } + } + invalidAssets = {}; + return removedAssets; } float PAGStage::getAssetMaxScale(ID referenceID) { - return getMaxScaleFactor(referenceID) * _cacheScale; + return getMaxScaleFactor(referenceID) * _cacheScale; } float PAGStage::getMaxScaleFactor(ID referenceID) { - auto result = scaleFactorCache.find(referenceID); - if (result != scaleFactorCache.end()) { - return result->second; - } - auto maxScaleFactor = calcMaxScaleFactor(referenceID); - if (maxScaleFactor == FLT_MIN) { - return 0; - } - scaleFactorCache[referenceID] = maxScaleFactor; - return maxScaleFactor; + auto result = scaleFactorCache.find(referenceID); + if (result != scaleFactorCache.end()) { + return result->second; + } + auto maxScaleFactor = calcMaxScaleFactor(referenceID); + if (maxScaleFactor == FLT_MIN) { + return 0; + } + scaleFactorCache[referenceID] = maxScaleFactor; + return maxScaleFactor; } float PAGStage::calcMaxScaleFactor(ID referenceID) { - auto reference = layerReferenceMap.find(referenceID); - if (reference == layerReferenceMap.end()) { - return FLT_MIN; - } - std::vector pagLayers = {}; - auto isPAGImage = pagImageMap.count(referenceID) > 0; - auto isPAGLayer = - reference->second.size() == 1 && reference->second.front()->uniqueID() == referenceID; + auto reference = layerReferenceMap.find(referenceID); + if (reference == layerReferenceMap.end()) { + return FLT_MIN; + } + std::vector pagLayers = {}; + auto isPAGImage = pagImageMap.count(referenceID) > 0; + auto isPAGLayer = + reference->second.size() == 1 && reference->second.front()->uniqueID() == referenceID; - auto func = [isPAGImage, isPAGLayer, &pagLayers](PAGLayer* pagLayer) { - // 内容修改过的图层有独立的缓存,若当前不是在计算 PAGImage 或 PAGLayer 的最大缩放值 - // (这两种情况下图层内容发生过修改),计算列表应该只考虑那些内容没被修改过的图层引用。 - if (isPAGImage || isPAGLayer || !pagLayer->contentModified()) { - pagLayers.push_back(pagLayer); - } - }; - std::for_each(reference->second.begin(), reference->second.end(), func); - if (pagLayers.empty()) { - return 0; - } - float maxScaleFactor = 0; - auto forEachFunc = [&maxScaleFactor, isPAGImage, this](PAGLayer* pagLayer) { - auto scale = GetLayerContentScaleFactor(pagLayer, isPAGImage); - auto scaleFactor = getLayerScaleFactor(pagLayer, scale); - if (scaleFactor > maxScaleFactor) { - maxScaleFactor = scaleFactor; - } - }; - std::for_each(pagLayers.begin(), pagLayers.end(), forEachFunc); - return maxScaleFactor; + auto func = [isPAGImage, isPAGLayer, &pagLayers](PAGLayer* pagLayer) { + // 内容修改过的图层有独立的缓存,若当前不是在计算 PAGImage 或 PAGLayer 的最大缩放值 + // (这两种情况下图层内容发生过修改),计算列表应该只考虑那些内容没被修改过的图层引用。 + if (isPAGImage || isPAGLayer || !pagLayer->contentModified()) { + pagLayers.push_back(pagLayer); + } + }; + std::for_each(reference->second.begin(), reference->second.end(), func); + if (pagLayers.empty()) { + return 0; + } + float maxScaleFactor = 0; + auto forEachFunc = [&maxScaleFactor, isPAGImage, this](PAGLayer* pagLayer) { + auto scale = GetLayerContentScaleFactor(pagLayer, isPAGImage); + auto scaleFactor = getLayerScaleFactor(pagLayer, scale); + if (scaleFactor > maxScaleFactor) { + maxScaleFactor = scaleFactor; + } + }; + std::for_each(pagLayers.begin(), pagLayers.end(), forEachFunc); + return maxScaleFactor; } Point PAGStage::GetLayerContentScaleFactor(PAGLayer* pagLayer, bool isPAGImage) { - Point scale = {1, 1}; - if (pagLayer->layerType() == LayerType::Image) { - if (isPAGImage) { - scale = static_cast(pagLayer)->replacement->getScaleFactor(); - } else { - scale.x = 1.0f / static_cast(pagLayer->layer)->imageBytes->scaleFactor; - scale.y = scale.x; - } - } else if (pagLayer->layerType() == LayerType::PreCompose) { - auto composition = - static_cast(static_cast(pagLayer)->layer)->composition; - if (composition->type() == CompositionType::Video || - composition->type() == CompositionType::Bitmap) { - auto sequence = Sequence::Get(composition); - scale.x = static_cast(composition->width) / static_cast(sequence->width); - scale.y = static_cast(composition->height) / static_cast(sequence->height); - } - } - return scale; + Point scale = {1, 1}; + if (pagLayer->layerType() == LayerType::Image) { + if (isPAGImage) { + scale = static_cast(pagLayer)->replacement->getScaleFactor(); + } else { + scale.x = 1.0f / static_cast(pagLayer->layer)->imageBytes->scaleFactor; + scale.y = scale.x; + } + } else if (pagLayer->layerType() == LayerType::PreCompose) { + auto composition = + static_cast(static_cast(pagLayer)->layer)->composition; + if (composition->type() == CompositionType::Video || + composition->type() == CompositionType::Bitmap) { + auto sequence = Sequence::Get(composition); + scale.x = static_cast(composition->width) / static_cast(sequence->width); + scale.y = static_cast(composition->height) / static_cast(sequence->height); + } + } + return scale; } float PAGStage::getLayerScaleFactor(PAGLayer* pagLayer, Point scale) { - auto parent = pagLayer; - while (parent) { - auto layerScaleFactor = parent->layerCache->getMaxScaleFactor(); - scale.x *= fabs(layerScaleFactor.x); - scale.y *= fabs(layerScaleFactor.y); - auto matrixScaleFactor = GetScaleFactor(parent->layerMatrix); - scale.x *= fabs(matrixScaleFactor.x); - scale.y *= fabs(matrixScaleFactor.y); - if (parent->_parent) { - parent = parent->_parent; - } else if (parent->trackMatteOwner) { - parent = parent->trackMatteOwner->_parent; - } else { - break; + auto parent = pagLayer; + while (parent) { + auto layerScaleFactor = parent->layerCache->getMaxScaleFactor(); + scale.x *= fabs(layerScaleFactor.x); + scale.y *= fabs(layerScaleFactor.y); + auto matrixScaleFactor = GetScaleFactor(parent->layerMatrix); + scale.x *= fabs(matrixScaleFactor.x); + scale.y *= fabs(matrixScaleFactor.y); + if (parent->_parent) { + parent = parent->_parent; + } else if (parent->trackMatteOwner) { + parent = parent->trackMatteOwner->_parent; + } else { + break; + } } - } - return std::max(scale.x, scale.y); + return std::max(scale.x, scale.y); } } // namespace pag diff --git a/src/rendering/layers/PAGStage.h b/src/rendering/layers/PAGStage.h index 36c0a4c48e..073910e3fe 100644 --- a/src/rendering/layers/PAGStage.h +++ b/src/rendering/layers/PAGStage.h @@ -27,104 +27,104 @@ namespace pag { struct SequenceCache { - std::shared_ptr graphic = nullptr; - Frame compositionFrame = 0; + std::shared_ptr graphic = nullptr; + Frame compositionFrame = 0; }; class PAGStage : public PAGComposition { - public: - static std::shared_ptr Make(int width, int height); - - ~PAGStage() override; - - /** - * This value defines the scale factor for internal graphics caches, ranges from 0.0 to 1.0. The - * scale factors less than 1.0 may result in blurred output, but it can reduce the usage of - * graphics memory which leads to better performance. - * The default value is 1.0. - */ - float cacheScale() const { - return _cacheScale; - } - - /** - * Set the value of cacheScale property. - */ - void setCacheScale(float value); - - /** - * Returns the first root composition. - */ - std::shared_ptr getRootComposition(); - - /** - * Returns the version of current content. - */ - uint32_t getContentVersion() const; - - /** - * Add a PAGLayer to this stage. - */ - void addReference(PAGLayer* pagLayer); - - /** - * Remove a PAGLayer from this stage. - */ - void removeReference(PAGLayer* pagLayer); - - /** - * Add a PAGImage to this stage. - */ - void addReference(PAGImage* pagImage, PAGLayer* pagLayer); - - /** - * Remove a PAGImage from this stage. - */ - void removeReference(PAGImage* pagImage, PAGLayer* pagLayer); - - /** - * Invalidate the content of a PAGLayer, it is usually called when a PAGLayer is edited. - */ - void invalidateCacheScale(PAGLayer* pagLayer); - - std::shared_ptr getSequenceGraphic(Composition* composition, Frame compositionFrame); - - std::map> findNearlyVisibleLayersIn(int64_t timeDistance); - - std::unordered_set getRemovedAssets(); - - float getAssetMaxScale(ID referenceID); - - protected: - void invalidateCacheScale() override { - PAGComposition::invalidateCacheScale(); - }; - - void onAddToStage(PAGStage*) override{}; - - void onRemoveFromStage() override{}; - - private: - float _cacheScale = 1.0f; - int64_t rootVersion = -1; - std::unordered_map layerStartTimeMap = {}; - std::unordered_map> layerReferenceMap = {}; - std::unordered_map scaleFactorCache = {}; - std::unordered_map sequenceCache = {}; - std::unordered_set invalidAssets = {}; - std::unordered_map pagImageMap = {}; - - static Point GetLayerContentScaleFactor(PAGLayer* pagLayer, bool isPAGImage); - PAGStage(int width, int height); - std::shared_ptr getSequenceFile(Sequence* sequence); - void addToReferenceMap(ID uniqueID, PAGLayer* pagLayer); - bool removeFromReferenceMap(ID uniqueID, PAGLayer* pagLayer); - float getMaxScaleFactor(ID referenceID); - float calcMaxScaleFactor(ID referenceID); - float getLayerScaleFactor(PAGLayer* pagLayer, Point scale); - void updateLayerStartTime(PAGLayer* pagLayer); - void updateChildLayerStartTime(PAGComposition* pagComposition); - - friend class RenderCache; +public: + static std::shared_ptr Make(int width, int height); + + ~PAGStage() override; + + /** + * This value defines the scale factor for internal graphics caches, ranges from 0.0 to 1.0. The + * scale factors less than 1.0 may result in blurred output, but it can reduce the usage of + * graphics memory which leads to better performance. + * The default value is 1.0. + */ + float cacheScale() const { + return _cacheScale; + } + + /** + * Set the value of cacheScale property. + */ + void setCacheScale(float value); + + /** + * Returns the first root composition. + */ + std::shared_ptr getRootComposition(); + + /** + * Returns the version of current content. + */ + uint32_t getContentVersion() const; + + /** + * Add a PAGLayer to this stage. + */ + void addReference(PAGLayer* pagLayer); + + /** + * Remove a PAGLayer from this stage. + */ + void removeReference(PAGLayer* pagLayer); + + /** + * Add a PAGImage to this stage. + */ + void addReference(PAGImage* pagImage, PAGLayer* pagLayer); + + /** + * Remove a PAGImage from this stage. + */ + void removeReference(PAGImage* pagImage, PAGLayer* pagLayer); + + /** + * Invalidate the content of a PAGLayer, it is usually called when a PAGLayer is edited. + */ + void invalidateCacheScale(PAGLayer* pagLayer); + + std::shared_ptr getSequenceGraphic(Composition* composition, Frame compositionFrame); + + std::map> findNearlyVisibleLayersIn(int64_t timeDistance); + + std::unordered_set getRemovedAssets(); + + float getAssetMaxScale(ID referenceID); + +protected: + void invalidateCacheScale() override { + PAGComposition::invalidateCacheScale(); + }; + + void onAddToStage(PAGStage*) override {}; + + void onRemoveFromStage() override {}; + +private: + float _cacheScale = 1.0f; + int64_t rootVersion = -1; + std::unordered_map layerStartTimeMap = {}; + std::unordered_map> layerReferenceMap = {}; + std::unordered_map scaleFactorCache = {}; + std::unordered_map sequenceCache = {}; + std::unordered_set invalidAssets = {}; + std::unordered_map pagImageMap = {}; + + static Point GetLayerContentScaleFactor(PAGLayer* pagLayer, bool isPAGImage); + PAGStage(int width, int height); + std::shared_ptr getSequenceFile(Sequence* sequence); + void addToReferenceMap(ID uniqueID, PAGLayer* pagLayer); + bool removeFromReferenceMap(ID uniqueID, PAGLayer* pagLayer); + float getMaxScaleFactor(ID referenceID); + float calcMaxScaleFactor(ID referenceID); + float getLayerScaleFactor(PAGLayer* pagLayer, Point scale); + void updateLayerStartTime(PAGLayer* pagLayer); + void updateChildLayerStartTime(PAGComposition* pagComposition); + + friend class RenderCache; }; } // namespace pag diff --git a/src/rendering/layers/PAGTextLayer.cpp b/src/rendering/layers/PAGTextLayer.cpp index 80a22a1c6d..b377528d3b 100644 --- a/src/rendering/layers/PAGTextLayer.cpp +++ b/src/rendering/layers/PAGTextLayer.cpp @@ -24,36 +24,36 @@ namespace pag { std::shared_ptr PAGTextLayer::Make(int64_t duration, std::string text, float fontSize, - std::string fontFamily, std::string fontStyle) { - if (duration <= 0) { - return nullptr; - } - auto textDocument = std::shared_ptr(new TextDocument()); - textDocument->text = std::move(text); - textDocument->fontSize = fontSize; - textDocument->fontFamily = std::move(fontFamily); - textDocument->fontStyle = std::move(fontStyle); - return Make(duration, textDocument); + std::string fontFamily, std::string fontStyle) { + if (duration <= 0) { + return nullptr; + } + auto textDocument = std::shared_ptr(new TextDocument()); + textDocument->text = std::move(text); + textDocument->fontSize = fontSize; + textDocument->fontFamily = std::move(fontFamily); + textDocument->fontStyle = std::move(fontStyle); + return Make(duration, textDocument); } std::shared_ptr PAGTextLayer::Make(int64_t duration, - std::shared_ptr textDocumentHandle) { - if (duration <= 0 || textDocumentHandle == nullptr) { - return nullptr; - } - auto layer = new TextLayer(); - auto transform = Transform2D::MakeDefault(); - transform->position->value = Point::Make(0, textDocumentHandle->fontSize); - layer->transform = transform; - auto sourceText = new Property(); - sourceText->value = std::move(textDocumentHandle); - layer->sourceText = sourceText; - - layer->duration = TimeToFrame(duration, 60); - auto textLayer = std::make_shared(nullptr, layer); - textLayer->emptyTextLayer = layer; - textLayer->weakThis = textLayer; - return textLayer; + std::shared_ptr textDocumentHandle) { + if (duration <= 0 || textDocumentHandle == nullptr) { + return nullptr; + } + auto layer = new TextLayer(); + auto transform = Transform2D::MakeDefault(); + transform->position->value = Point::Make(0, textDocumentHandle->fontSize); + layer->transform = transform; + auto sourceText = new Property(); + sourceText->value = std::move(textDocumentHandle); + layer->sourceText = sourceText; + + layer->duration = TimeToFrame(duration, 60); + auto textLayer = std::make_shared(nullptr, layer); + textLayer->emptyTextLayer = layer; + textLayer->weakThis = textLayer; + return textLayer; } PAGTextLayer::PAGTextLayer(std::shared_ptr file, TextLayer* layer) @@ -61,127 +61,127 @@ PAGTextLayer::PAGTextLayer(std::shared_ptr file, TextLayer* layer) } PAGTextLayer::~PAGTextLayer() { - delete replacement; - delete emptyTextLayer; + delete replacement; + delete emptyTextLayer; } Color PAGTextLayer::fillColor() const { - LockGuard autoLock(rootLocker); - return textDocumentForRead()->fillColor; + LockGuard autoLock(rootLocker); + return textDocumentForRead()->fillColor; } void PAGTextLayer::setFillColor(const Color& value) { - LockGuard autoLock(rootLocker); - textDocumentForWrite()->fillColor = value; + LockGuard autoLock(rootLocker); + textDocumentForWrite()->fillColor = value; } PAGFont PAGTextLayer::font() const { - LockGuard autoLock(rootLocker); - auto textDocument = textDocumentForRead(); - return {textDocument->fontFamily, textDocument->fontStyle}; + LockGuard autoLock(rootLocker); + auto textDocument = textDocumentForRead(); + return {textDocument->fontFamily, textDocument->fontStyle}; } void PAGTextLayer::setFont(const PAGFont& font) { - LockGuard autoLock(rootLocker); - auto textDocument = textDocumentForWrite(); - textDocument->fontFamily = font.fontFamily; - textDocument->fontStyle = font.fontStyle; + LockGuard autoLock(rootLocker); + auto textDocument = textDocumentForWrite(); + textDocument->fontFamily = font.fontFamily; + textDocument->fontStyle = font.fontStyle; } float PAGTextLayer::fontSize() const { - LockGuard autoLock(rootLocker); - return textDocumentForRead()->fontSize; + LockGuard autoLock(rootLocker); + return textDocumentForRead()->fontSize; } void PAGTextLayer::setFontSize(float size) { - LockGuard autoLock(rootLocker); - textDocumentForWrite()->fontSize = size; + LockGuard autoLock(rootLocker); + textDocumentForWrite()->fontSize = size; } Color PAGTextLayer::strokeColor() const { - LockGuard autoLock(rootLocker); - return textDocumentForRead()->strokeColor; + LockGuard autoLock(rootLocker); + return textDocumentForRead()->strokeColor; } void PAGTextLayer::setStrokeColor(const Color& color) { - LockGuard autoLock(rootLocker); - textDocumentForWrite()->strokeColor = color; + LockGuard autoLock(rootLocker); + textDocumentForWrite()->strokeColor = color; } std::string PAGTextLayer::text() const { - LockGuard autoLock(rootLocker); - return textDocumentForRead()->text; + LockGuard autoLock(rootLocker); + return textDocumentForRead()->text; } void PAGTextLayer::setText(const std::string& text) { - LockGuard autoLock(rootLocker); - textDocumentForWrite()->text = text; + LockGuard autoLock(rootLocker); + textDocumentForWrite()->text = text; } void PAGTextLayer::replaceTextInternal(std::shared_ptr textData) { - if (textData == nullptr) { - reset(); - } else { - auto textDocument = textDocumentForWrite(); - // 仅以下属性支持外部修改: - textDocument->applyFill = textData->applyFill; - textDocument->applyStroke = textData->applyStroke; - textDocument->fauxBold = textData->fauxBold; - textDocument->fauxItalic = textData->fauxItalic; - textDocument->fillColor = textData->fillColor; - textDocument->fontFamily = textData->fontFamily; - textDocument->fontStyle = textData->fontStyle; - textDocument->fontSize = textData->fontSize; - textDocument->strokeColor = textData->strokeColor; - textDocument->strokeWidth = textData->strokeWidth; - textDocument->text = textData->text; - textDocument->backgroundColor = textData->backgroundColor; - textDocument->backgroundAlpha = textData->backgroundAlpha; - textDocument->justification = textData->justification; - } + if (textData == nullptr) { + reset(); + } else { + auto textDocument = textDocumentForWrite(); + // 仅以下属性支持外部修改: + textDocument->applyFill = textData->applyFill; + textDocument->applyStroke = textData->applyStroke; + textDocument->fauxBold = textData->fauxBold; + textDocument->fauxItalic = textData->fauxItalic; + textDocument->fillColor = textData->fillColor; + textDocument->fontFamily = textData->fontFamily; + textDocument->fontStyle = textData->fontStyle; + textDocument->fontSize = textData->fontSize; + textDocument->strokeColor = textData->strokeColor; + textDocument->strokeWidth = textData->strokeWidth; + textDocument->text = textData->text; + textDocument->backgroundColor = textData->backgroundColor; + textDocument->backgroundAlpha = textData->backgroundAlpha; + textDocument->justification = textData->justification; + } } const TextDocument* PAGTextLayer::textDocumentForRead() const { - return replacement ? replacement->getTextDocument() - : static_cast(layer)->sourceText->value.get(); + return replacement ? replacement->getTextDocument() + : static_cast(layer)->sourceText->value.get(); } TextDocument* PAGTextLayer::textDocumentForWrite() { - if (replacement == nullptr) { - replacement = new TextReplacement(this); - } else { - replacement->clearCache(); - } - notifyModified(true); - invalidateCacheScale(); - return replacement->getTextDocument(); + if (replacement == nullptr) { + replacement = new TextReplacement(this); + } else { + replacement->clearCache(); + } + notifyModified(true); + invalidateCacheScale(); + return replacement->getTextDocument(); } void PAGTextLayer::reset() { - if (replacement != nullptr) { - delete replacement; - replacement = nullptr; - notifyModified(true); - invalidateCacheScale(); - } + if (replacement != nullptr) { + delete replacement; + replacement = nullptr; + notifyModified(true); + invalidateCacheScale(); + } } Content* PAGTextLayer::getContent() { - if (replacement != nullptr) { - return replacement->getContent(contentFrame); - } - return layerCache->getContent(contentFrame); + if (replacement != nullptr) { + return replacement->getContent(contentFrame); + } + return layerCache->getContent(contentFrame); } bool PAGTextLayer::contentModified() const { - return replacement != nullptr; + return replacement != nullptr; } void PAGTextLayer::setMatrixInternal(const Matrix& matrix) { - if (matrix == layerMatrix) { - return; - } - PAGLayer::setMatrixInternal(matrix); + if (matrix == layerMatrix) { + return; + } + PAGLayer::setMatrixInternal(matrix); } } // namespace pag diff --git a/src/rendering/readers/BitmapDecodingTask.cpp b/src/rendering/readers/BitmapDecodingTask.cpp index 9e46731c0c..3ab9765bef 100644 --- a/src/rendering/readers/BitmapDecodingTask.cpp +++ b/src/rendering/readers/BitmapDecodingTask.cpp @@ -20,14 +20,14 @@ namespace pag { std::shared_ptr BitmapDecodingTask::MakeAndRun(BitmapSequenceReader* reader, - Frame targetFrame) { - if (reader == nullptr) { - return nullptr; - } - auto executor = new BitmapDecodingTask(reader, targetFrame); - auto task = Task::Make(std::unique_ptr(executor)); - task->run(); - return task; + Frame targetFrame) { + if (reader == nullptr) { + return nullptr; + } + auto executor = new BitmapDecodingTask(reader, targetFrame); + auto task = Task::Make(std::unique_ptr(executor)); + task->run(); + return task; } BitmapDecodingTask::BitmapDecodingTask(BitmapSequenceReader* reader, Frame targetFrame) @@ -35,6 +35,6 @@ BitmapDecodingTask::BitmapDecodingTask(BitmapSequenceReader* reader, Frame targe } void BitmapDecodingTask::execute() { - reader->decodeFrame(targetFrame); + reader->decodeFrame(targetFrame); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/readers/BitmapDecodingTask.h b/src/rendering/readers/BitmapDecodingTask.h index 0d950ce9e7..09228885bf 100644 --- a/src/rendering/readers/BitmapDecodingTask.h +++ b/src/rendering/readers/BitmapDecodingTask.h @@ -23,14 +23,14 @@ namespace pag { class BitmapDecodingTask : public Executor { - public: - static std::shared_ptr MakeAndRun(BitmapSequenceReader* reader, Frame targetFrame); +public: + static std::shared_ptr MakeAndRun(BitmapSequenceReader* reader, Frame targetFrame); - private: - BitmapSequenceReader* reader = nullptr; - Frame targetFrame = 0; +private: + BitmapSequenceReader* reader = nullptr; + Frame targetFrame = 0; - BitmapDecodingTask(BitmapSequenceReader* reader, Frame targetFrame); - void execute() override; + BitmapDecodingTask(BitmapSequenceReader* reader, Frame targetFrame); + void execute() override; }; } // namespace pag \ No newline at end of file diff --git a/src/rendering/readers/BitmapSequenceReader.cpp b/src/rendering/readers/BitmapSequenceReader.cpp index 0f3359d12a..9e37002d1c 100644 --- a/src/rendering/readers/BitmapSequenceReader.cpp +++ b/src/rendering/readers/BitmapSequenceReader.cpp @@ -24,92 +24,92 @@ namespace pag { BitmapSequenceReader::BitmapSequenceReader(std::shared_ptr file, BitmapSequence* sequence) : SequenceReader(std::move(file), sequence) { - // 若内容非静态,强制使用非 hardware 的 Bitmap,否则纹理内容跟 bitmap - // 内存是共享的,无法进行解码预测。 - if (bitmap.allocPixels(sequence->width, sequence->height, false, staticContent)) { - // 必须清零,否则首帧是空帧的情况会绘制错误。 - bitmap.eraseAll(); - } + // 若内容非静态,强制使用非 hardware 的 Bitmap,否则纹理内容跟 bitmap + // 内存是共享的,无法进行解码预测。 + if (bitmap.allocPixels(sequence->width, sequence->height, false, staticContent)) { + // 必须清零,否则首帧是空帧的情况会绘制错误。 + bitmap.eraseAll(); + } } void BitmapSequenceReader::decodeFrame(Frame targetFrame) { - // decodeBitmap 这里需要立即加锁,防止异步解码时线程冲突。 - std::lock_guard autoLock(locker); - if (lastDecodeFrame == targetFrame || bitmap.isEmpty()) { - return; - } - auto startFrame = findStartFrame(targetFrame); - auto& bitmapFrames = static_cast(sequence)->frames; - BitmapLock bitmapLock(bitmap); - auto pixels = bitmapLock.pixels(); - for (Frame frame = startFrame; frame <= targetFrame; frame++) { - auto bitmapFrame = bitmapFrames[frame]; - auto firstRead = true; - for (auto bitmapRect : bitmapFrame->bitmaps) { - auto imageBytes = - Data::MakeWithoutCopy(bitmapRect->fileBytes->data(), bitmapRect->fileBytes->length()); - auto image = Image::MakeFrom(imageBytes); - if (image != nullptr) { - // 关键帧不是全屏的时候要清屏 - if (firstRead && bitmapFrame->isKeyframe && - !(image->width() == bitmap.width() && image->height() == bitmap.height())) { - memset(pixels, 0, bitmap.byteSize()); + // decodeBitmap 这里需要立即加锁,防止异步解码时线程冲突。 + std::lock_guard autoLock(locker); + if (lastDecodeFrame == targetFrame || bitmap.isEmpty()) { + return; + } + auto startFrame = findStartFrame(targetFrame); + auto& bitmapFrames = static_cast(sequence)->frames; + BitmapLock bitmapLock(bitmap); + auto pixels = bitmapLock.pixels(); + for (Frame frame = startFrame; frame <= targetFrame; frame++) { + auto bitmapFrame = bitmapFrames[frame]; + auto firstRead = true; + for (auto bitmapRect : bitmapFrame->bitmaps) { + auto imageBytes = + Data::MakeWithoutCopy(bitmapRect->fileBytes->data(), bitmapRect->fileBytes->length()); + auto image = Image::MakeFrom(imageBytes); + if (image != nullptr) { + // 关键帧不是全屏的时候要清屏 + if (firstRead && bitmapFrame->isKeyframe && + !(image->width() == bitmap.width() && image->height() == bitmap.height())) { + memset(pixels, 0, bitmap.byteSize()); + } + auto offset = bitmap.rowBytes() * bitmapRect->y + bitmapRect->x * 4; + image->readPixels(bitmap.info(), reinterpret_cast(pixels) + offset); + firstRead = false; + } } - auto offset = bitmap.rowBytes() * bitmapRect->y + bitmapRect->x * 4; - image->readPixels(bitmap.info(), reinterpret_cast(pixels) + offset); - firstRead = false; - } + lastDecodeFrame = targetFrame; } - lastDecodeFrame = targetFrame; - } } Frame BitmapSequenceReader::findStartFrame(Frame targetFrame) { - Frame startFrame = 0; - auto& bitmapFrames = static_cast(sequence)->frames; - for (Frame frame = targetFrame; frame >= 0; frame--) { - if (frame == lastDecodeFrame + 1 || bitmapFrames[static_cast(frame)]->isKeyframe) { - startFrame = frame; - break; + Frame startFrame = 0; + auto& bitmapFrames = static_cast(sequence)->frames; + for (Frame frame = targetFrame; frame >= 0; frame--) { + if (frame == lastDecodeFrame + 1 || bitmapFrames[static_cast(frame)]->isKeyframe) { + startFrame = frame; + break; + } } - } - return startFrame; + return startFrame; } void BitmapSequenceReader::prepareAsync(Frame targetFrame) { - if (lastTask != nullptr) { - if (lastTextureFrame != -1) { - pendingFrame = targetFrame; + if (lastTask != nullptr) { + if (lastTextureFrame != -1) { + pendingFrame = targetFrame; + } + } else { + lastTask = BitmapDecodingTask::MakeAndRun(this, targetFrame); } - } else { - lastTask = BitmapDecodingTask::MakeAndRun(this, targetFrame); - } } std::shared_ptr BitmapSequenceReader::readTexture(Frame targetFrame, RenderCache* cache) { - if (lastTextureFrame == targetFrame || bitmap.isEmpty()) { - return lastTexture; - } - auto startTime = GetTimer(); - // 必须提前置空,否则会出现对 Bitmap 写入的竞争导致内容不一致,或者死锁,析构会触发 cancel(), - // 可能会阻塞当前线程。 - lastTask = nullptr; - decodeFrame(targetFrame); - cache->imageDecodingTime += GetTimer() - startTime; - lastTexture = nullptr; // 先释放上一次的 Texture,允许在 Context 里复用。 - startTime = GetTimer(); - lastTexture = bitmap.makeTexture(cache->getContext()); - lastTextureFrame = targetFrame; - cache->textureUploadingTime += GetTimer() - startTime; - if (!staticContent) { - auto nextFrame = targetFrame + 1; - if (nextFrame >= sequence->duration() && pendingFrame >= 0) { - nextFrame = pendingFrame; - pendingFrame = -1; + if (lastTextureFrame == targetFrame || bitmap.isEmpty()) { + return lastTexture; } - if (nextFrame < sequence->duration()) { - lastTask = BitmapDecodingTask::MakeAndRun(this, nextFrame); + auto startTime = GetTimer(); + // 必须提前置空,否则会出现对 Bitmap 写入的竞争导致内容不一致,或者死锁,析构会触发 cancel(), + // 可能会阻塞当前线程。 + lastTask = nullptr; + decodeFrame(targetFrame); + cache->imageDecodingTime += GetTimer() - startTime; + lastTexture = nullptr; // 先释放上一次的 Texture,允许在 Context 里复用。 + startTime = GetTimer(); + lastTexture = bitmap.makeTexture(cache->getContext()); + lastTextureFrame = targetFrame; + cache->textureUploadingTime += GetTimer() - startTime; + if (!staticContent) { + auto nextFrame = targetFrame + 1; + if (nextFrame >= sequence->duration() && pendingFrame >= 0) { + nextFrame = pendingFrame; + pendingFrame = -1; + } + if (nextFrame < sequence->duration()) { + lastTask = BitmapDecodingTask::MakeAndRun(this, nextFrame); + } } - } - return lastTexture; + return lastTexture; } } // namespace pag diff --git a/src/rendering/readers/BitmapSequenceReader.h b/src/rendering/readers/BitmapSequenceReader.h index 92df0b4323..6718808e01 100644 --- a/src/rendering/readers/BitmapSequenceReader.h +++ b/src/rendering/readers/BitmapSequenceReader.h @@ -25,24 +25,24 @@ namespace pag { class BitmapSequenceReader : public SequenceReader { - public: - BitmapSequenceReader(std::shared_ptr file, BitmapSequence* sequence); +public: + BitmapSequenceReader(std::shared_ptr file, BitmapSequence* sequence); - void decodeFrame(Frame targetFrame); + void decodeFrame(Frame targetFrame); - void prepareAsync(Frame targetFrame) override; + void prepareAsync(Frame targetFrame) override; - std::shared_ptr readTexture(Frame frame, RenderCache* cache) override; + std::shared_ptr readTexture(Frame frame, RenderCache* cache) override; - private: - std::mutex locker = {}; - Frame lastDecodeFrame = -1; - Frame lastTextureFrame = -1; - Frame pendingFrame = -1; - Bitmap bitmap = {}; - std::shared_ptr lastTexture = nullptr; - std::shared_ptr lastTask = nullptr; +private: + std::mutex locker = {}; + Frame lastDecodeFrame = -1; + Frame lastTextureFrame = -1; + Frame pendingFrame = -1; + Bitmap bitmap = {}; + std::shared_ptr lastTexture = nullptr; + std::shared_ptr lastTask = nullptr; - Frame findStartFrame(Frame targetFrame); + Frame findStartFrame(Frame targetFrame); }; } // namespace pag diff --git a/src/rendering/readers/SequenceReader.cpp b/src/rendering/readers/SequenceReader.cpp index e551d2540b..f7990dab3a 100644 --- a/src/rendering/readers/SequenceReader.cpp +++ b/src/rendering/readers/SequenceReader.cpp @@ -21,6 +21,6 @@ namespace pag { SequenceReader::SequenceReader(std::shared_ptr file, Sequence* sequence) : file(std::move(file)), sequence(sequence) { - staticContent = sequence->composition->staticContent(); + staticContent = sequence->composition->staticContent(); } } // namespace pag diff --git a/src/rendering/readers/SequenceReader.h b/src/rendering/readers/SequenceReader.h index f671ad7034..2979667b17 100644 --- a/src/rendering/readers/SequenceReader.h +++ b/src/rendering/readers/SequenceReader.h @@ -27,27 +27,27 @@ namespace pag { class RenderCache; class SequenceReader { - public: - static std::shared_ptr - Make(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy policy); +public: + static std::shared_ptr + Make(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy policy); - SequenceReader(std::shared_ptr file, Sequence* sequence); + SequenceReader(std::shared_ptr file, Sequence* sequence); - virtual ~SequenceReader() = default; + virtual ~SequenceReader() = default; - Sequence* getSequence() const { - return sequence; - } + Sequence* getSequence() const { + return sequence; + } - virtual void prepareAsync(Frame targetFrame) = 0; + virtual void prepareAsync(Frame targetFrame) = 0; - virtual std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) = 0; + virtual std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) = 0; - protected: - // 持有 File 引用,防止在异步解码时 Sequence 被析构。 - std::shared_ptr file = nullptr; - Sequence* sequence = nullptr; - bool staticContent = false; +protected: + // 持有 File 引用,防止在异步解码时 Sequence 被析构。 + std::shared_ptr file = nullptr; + Sequence* sequence = nullptr; + bool staticContent = false; }; } // namespace pag diff --git a/src/rendering/renderers/CompositionRenderer.cpp b/src/rendering/renderers/CompositionRenderer.cpp index da421edf93..00be85bd5d 100644 --- a/src/rendering/renderers/CompositionRenderer.cpp +++ b/src/rendering/renderers/CompositionRenderer.cpp @@ -26,97 +26,98 @@ namespace pag { class SequenceProxy : public TextureProxy { - public: - SequenceProxy(Sequence* sequence, Frame frame, int width, int height) - : TextureProxy(width, height), sequence(sequence), frame(frame) { - } +public: + SequenceProxy(Sequence* sequence, Frame frame, int width, int height) + : TextureProxy(width, height), sequence(sequence), frame(frame) { + } - bool cacheEnabled() const override { - return !sequence->composition->staticContent(); - } + bool cacheEnabled() const override { + return !sequence->composition->staticContent(); + } - void prepare(RenderCache* cache) const override { - static_cast(cache)->prepareSequenceReader(sequence, frame, - DecodingPolicy::SoftwareToHardware); - } + void prepare(RenderCache* cache) const override { + static_cast(cache)->prepareSequenceReader(sequence, frame, + DecodingPolicy::SoftwareToHardware); + } - std::shared_ptr getTexture(RenderCache* cache) const override { - auto reader = static_cast(cache)->getSequenceReader(sequence); - if (reader) { - return reader->readTexture(frame, static_cast(cache)); + std::shared_ptr getTexture(RenderCache* cache) const override { + auto reader = static_cast(cache)->getSequenceReader(sequence); + if (reader) { + return reader->readTexture(frame, static_cast(cache)); + } + return nullptr; } - return nullptr; - } - private: - Sequence* sequence = nullptr; - Frame frame = 0; +private: + Sequence* sequence = nullptr; + Frame frame = 0; }; static std::shared_ptr MakeVideoSequenceGraphic(VideoSequence* sequence, - Frame contentFrame) { - // 视频序列帧导出时没有记录准确的画面总宽高,需要自己通过 width 和 alphaStartX 计算, - // 如果遇到奇数尺寸导出插件会自动加一,这里匹配导出插件的规则。 - auto videoWidth = sequence->alphaStartX + sequence->width; - if (videoWidth % 2 == 1) { - videoWidth++; - } - auto videoHeight = sequence->alphaStartY + sequence->height; - if (videoHeight % 2 == 1) { - videoHeight++; - } - auto proxy = new SequenceProxy(sequence, contentFrame, videoWidth, videoHeight); - RGBAAALayout layout = {sequence->width, sequence->height, sequence->alphaStartX, - sequence->alphaStartY}; - return Picture::MakeFrom(sequence->composition->uniqueID, std::unique_ptr(proxy), - layout); + Frame contentFrame) { + // 视频序列帧导出时没有记录准确的画面总宽高,需要自己通过 width 和 alphaStartX 计算, + // 如果遇到奇数尺寸导出插件会自动加一,这里匹配导出插件的规则。 + auto videoWidth = sequence->alphaStartX + sequence->width; + if (videoWidth % 2 == 1) { + videoWidth++; + } + auto videoHeight = sequence->alphaStartY + sequence->height; + if (videoHeight % 2 == 1) { + videoHeight++; + } + auto proxy = new SequenceProxy(sequence, contentFrame, videoWidth, videoHeight); + RGBAAALayout layout = {sequence->width, sequence->height, sequence->alphaStartX, + sequence->alphaStartY + }; + return Picture::MakeFrom(sequence->composition->uniqueID, std::unique_ptr(proxy), + layout); } std::shared_ptr RenderVectorComposition(VectorComposition* composition, - Frame compositionFrame) { - Recorder recorder = {}; - recorder.saveClip(0, 0, static_cast(composition->width), - static_cast(composition->height)); - auto& layers = composition->layers; - // The index order of Layers in File is different from PAGLayers. - for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { - auto childLayer = layers[i]; - if (!childLayer->isActive) { - continue; + Frame compositionFrame) { + Recorder recorder = {}; + recorder.saveClip(0, 0, static_cast(composition->width), + static_cast(composition->height)); + auto& layers = composition->layers; + // The index order of Layers in File is different from PAGLayers. + for (int i = static_cast(layers.size()) - 1; i >= 0; i--) { + auto childLayer = layers[i]; + if (!childLayer->isActive) { + continue; + } + auto layerCache = LayerCache::Get(childLayer); + auto filterModifier = + layerCache->cacheFilters() ? nullptr : FilterModifier::Make(childLayer, compositionFrame); + auto trackMatte = TrackMatteRenderer::Make(childLayer, compositionFrame); + LayerRenderer::DrawLayer(&recorder, childLayer, compositionFrame, filterModifier, + trackMatte.get()); + } + recorder.restore(); + auto graphic = recorder.makeGraphic(); + if (layers.size() > 1 && composition->staticContent() && !composition->hasImageContent()) { + // 仅当子项列表只存在矢量内容并图层数量大于 1 时才包装一个 Image,避免重复的 Image 包装。 + graphic = Picture::MakeFrom(composition->uniqueID, graphic); } - auto layerCache = LayerCache::Get(childLayer); - auto filterModifier = - layerCache->cacheFilters() ? nullptr : FilterModifier::Make(childLayer, compositionFrame); - auto trackMatte = TrackMatteRenderer::Make(childLayer, compositionFrame); - LayerRenderer::DrawLayer(&recorder, childLayer, compositionFrame, filterModifier, - trackMatte.get()); - } - recorder.restore(); - auto graphic = recorder.makeGraphic(); - if (layers.size() > 1 && composition->staticContent() && !composition->hasImageContent()) { - // 仅当子项列表只存在矢量内容并图层数量大于 1 时才包装一个 Image,避免重复的 Image 包装。 - graphic = Picture::MakeFrom(composition->uniqueID, graphic); - } - return graphic; + return graphic; } std::shared_ptr RenderSequenceComposition(Composition* composition, - Frame compositionFrame) { - auto sequence = Sequence::Get(composition); - if (sequence == nullptr) { - return nullptr; - } - auto sequenceFrame = sequence->toSequenceFrame(compositionFrame); - std::shared_ptr graphic = nullptr; - if (composition->type() == CompositionType::Video) { - graphic = MakeVideoSequenceGraphic(static_cast(sequence), sequenceFrame); - } else { - auto proxy = new SequenceProxy(sequence, sequenceFrame, sequence->width, sequence->height); - graphic = - Picture::MakeFrom(sequence->composition->uniqueID, std::unique_ptr(proxy)); - } - auto scaleX = static_cast(composition->width) / static_cast(sequence->width); - auto scaleY = static_cast(composition->height) / static_cast(sequence->height); - return Graphic::MakeCompose(graphic, Matrix::MakeScale(scaleX, scaleY)); + Frame compositionFrame) { + auto sequence = Sequence::Get(composition); + if (sequence == nullptr) { + return nullptr; + } + auto sequenceFrame = sequence->toSequenceFrame(compositionFrame); + std::shared_ptr graphic = nullptr; + if (composition->type() == CompositionType::Video) { + graphic = MakeVideoSequenceGraphic(static_cast(sequence), sequenceFrame); + } else { + auto proxy = new SequenceProxy(sequence, sequenceFrame, sequence->width, sequence->height); + graphic = + Picture::MakeFrom(sequence->composition->uniqueID, std::unique_ptr(proxy)); + } + auto scaleX = static_cast(composition->width) / static_cast(sequence->width); + auto scaleY = static_cast(composition->height) / static_cast(sequence->height); + return Graphic::MakeCompose(graphic, Matrix::MakeScale(scaleX, scaleY)); } } // namespace pag \ No newline at end of file diff --git a/src/rendering/renderers/CompositionRenderer.h b/src/rendering/renderers/CompositionRenderer.h index 97a0418298..b1b7100a5f 100644 --- a/src/rendering/renderers/CompositionRenderer.h +++ b/src/rendering/renderers/CompositionRenderer.h @@ -23,8 +23,8 @@ namespace pag { std::shared_ptr RenderVectorComposition(VectorComposition* composition, - Frame compositionFrame); + Frame compositionFrame); std::shared_ptr RenderSequenceComposition(Composition* composition, - Frame compositionFrame); + Frame compositionFrame); } // namespace pag \ No newline at end of file diff --git a/src/rendering/renderers/FilterRenderer.cpp b/src/rendering/renderers/FilterRenderer.cpp index 1ec0d65029..9ed50675f4 100644 --- a/src/rendering/renderers/FilterRenderer.cpp +++ b/src/rendering/renderers/FilterRenderer.cpp @@ -33,442 +33,442 @@ namespace pag { #define FAST_BLUR_MAX_SCALE_FACTOR 0.1f float GetScaleFactorLimit(Layer* layer) { - auto scaleFactorLimit = layer->type() == LayerType::Image ? 1.0f : FLT_MAX; - return scaleFactorLimit; + auto scaleFactorLimit = layer->type() == LayerType::Image ? 1.0f : FLT_MAX; + return scaleFactorLimit; } bool DoesProcessVisibleAreaOnly(Layer* layer) { - for (auto& effect : layer->effects) { - if (!effect->processVisibleAreaOnly()) { - return false; + for (auto& effect : layer->effects) { + if (!effect->processVisibleAreaOnly()) { + return false; + } } - } - return true; + return true; } std::unique_ptr FilterRenderer::MakeFilterList(const FilterModifier* modifier) { - auto filterList = std::unique_ptr(new FilterList()); - auto layer = modifier->layer; - auto layerFrame = modifier->layerFrame; - filterList->layer = layer; - filterList->layerFrame = layerFrame; - auto contentFrame = layerFrame - layer->startTime; - filterList->layerMatrix = LayerCache::Get(layer)->getTransform(contentFrame)->matrix; - filterList->scaleFactorLimit = GetScaleFactorLimit(filterList->layer); - filterList->processVisibleAreaOnly = DoesProcessVisibleAreaOnly(filterList->layer); - for (auto& effect : layer->effects) { - if (effect->visibleAt(layerFrame)) { - filterList->effects.push_back(effect); - } - } - for (auto& layerStyle : layer->layerStyles) { - if (layerStyle->visibleAt(layerFrame)) { - filterList->layerStyles.push_back(layerStyle); - } - } - // 当存在非只处理可见区域的Effect滤镜时,对于Shape和Text图层会直接取父级Composition的的尺寸, - // 应用图层本身的matrix之后再作为 - // 输入纹理,超出部分截断。而对于Solid,Image,PreCompose按内容实际尺寸作为输入纹理,并且不包含图层本身 - // 的matrix。 - auto needParentSizeInput = !layer->effects.empty() && (layer->type() == LayerType::Shape || - layer->type() == LayerType::Text); - filterList->useParentSizeInput = !filterList->processVisibleAreaOnly && needParentSizeInput; - if (!filterList->useParentSizeInput) { - // LayerStyle本应该在图层matrix之后应用的,但是我们为了简化渲染改到了matrix之前,因此需要反向排除图层matrix的缩放值。 - filterList->layerStyleScale = GetScaleFactor(filterList->layerMatrix, 1.0f, true); - if (needParentSizeInput) { - // 含有本应该在图层matrix之后应用的Effect,但是我们为了简化渲染改到了matrix之前,因此需要反向排除图层matrix - // 的缩放值。 - filterList->effectScale = filterList->layerStyleScale; - } - } + auto filterList = std::unique_ptr(new FilterList()); + auto layer = modifier->layer; + auto layerFrame = modifier->layerFrame; + filterList->layer = layer; + filterList->layerFrame = layerFrame; + auto contentFrame = layerFrame - layer->startTime; + filterList->layerMatrix = LayerCache::Get(layer)->getTransform(contentFrame)->matrix; + filterList->scaleFactorLimit = GetScaleFactorLimit(filterList->layer); + filterList->processVisibleAreaOnly = DoesProcessVisibleAreaOnly(filterList->layer); + for (auto& effect : layer->effects) { + if (effect->visibleAt(layerFrame)) { + filterList->effects.push_back(effect); + } + } + for (auto& layerStyle : layer->layerStyles) { + if (layerStyle->visibleAt(layerFrame)) { + filterList->layerStyles.push_back(layerStyle); + } + } + // 当存在非只处理可见区域的Effect滤镜时,对于Shape和Text图层会直接取父级Composition的的尺寸, + // 应用图层本身的matrix之后再作为 + // 输入纹理,超出部分截断。而对于Solid,Image,PreCompose按内容实际尺寸作为输入纹理,并且不包含图层本身 + // 的matrix。 + auto needParentSizeInput = !layer->effects.empty() && (layer->type() == LayerType::Shape || + layer->type() == LayerType::Text); + filterList->useParentSizeInput = !filterList->processVisibleAreaOnly && needParentSizeInput; + if (!filterList->useParentSizeInput) { + // LayerStyle本应该在图层matrix之后应用的,但是我们为了简化渲染改到了matrix之前,因此需要反向排除图层matrix的缩放值。 + filterList->layerStyleScale = GetScaleFactor(filterList->layerMatrix, 1.0f, true); + if (needParentSizeInput) { + // 含有本应该在图层matrix之后应用的Effect,但是我们为了简化渲染改到了matrix之前,因此需要反向排除图层matrix + // 的缩放值。 + filterList->effectScale = filterList->layerStyleScale; + } + } - return filterList; + return filterList; } Rect FilterRenderer::GetParentBounds(const FilterList* filterList) { - auto layer = filterList->layer; - float width, height; - switch (layer->type()) { + auto layer = filterList->layer; + float width, height; + switch (layer->type()) { case LayerType::Shape: // fall through case LayerType::Text: - // 对于Shape和Text一定有containingComposition。 - width = layer->containingComposition->width; - height = layer->containingComposition->height; - break; + // 对于Shape和Text一定有containingComposition。 + width = layer->containingComposition->width; + height = layer->containingComposition->height; + break; case LayerType::Solid: - width = static_cast(layer)->width; - height = static_cast(layer)->height; - break; + width = static_cast(layer)->width; + height = static_cast(layer)->height; + break; case LayerType::Image: - width = static_cast(layer)->imageBytes->width; - height = static_cast(layer)->imageBytes->height; - break; + width = static_cast(layer)->imageBytes->width; + height = static_cast(layer)->imageBytes->height; + break; case LayerType::PreCompose: - width = static_cast(layer)->composition->width; - height = static_cast(layer)->composition->height; - break; + width = static_cast(layer)->composition->width; + height = static_cast(layer)->composition->height; + break; default: - width = height = 0; - break; - } - return Rect::MakeXYWH(0, 0, width, height); + width = height = 0; + break; + } + return Rect::MakeXYWH(0, 0, width, height); } Rect FilterRenderer::GetContentBounds(const FilterList* filterList, std::shared_ptr content) { - Rect contentBounds = Rect::MakeEmpty(); - if (filterList->processVisibleAreaOnly) { - content->measureBounds(&contentBounds); - contentBounds.roundOut(); - } else { - contentBounds = GetParentBounds(filterList); - } - return contentBounds; + Rect contentBounds = Rect::MakeEmpty(); + if (filterList->processVisibleAreaOnly) { + content->measureBounds(&contentBounds); + contentBounds.roundOut(); + } else { + contentBounds = GetParentBounds(filterList); + } + return contentBounds; } void TransformFilterBounds(Rect* filterBounds, const FilterList* filterList) { - // 滤镜应用顺序:Effects->motionBlur->LayerStyles - for (auto& effect : filterList->effects) { - effect->transformBounds(filterBounds, filterList->effectScale, filterList->layerFrame); - filterBounds->roundOut(); - } + // 滤镜应用顺序:Effects->motionBlur->LayerStyles + for (auto& effect : filterList->effects) { + effect->transformBounds(filterBounds, filterList->effectScale, filterList->layerFrame); + filterBounds->roundOut(); + } - if (filterList->layer->motionBlur) { - MotionBlurFilter::TransformBounds(filterBounds, filterList->effectScale, filterList->layer, - filterList->layerFrame); - } + if (filterList->layer->motionBlur) { + MotionBlurFilter::TransformBounds(filterBounds, filterList->effectScale, filterList->layer, + filterList->layerFrame); + } - if (!filterList->layerStyles.empty()) { - LayerStylesFilter::TransformBounds(filterBounds, filterList); - } + if (!filterList->layerStyles.empty()) { + LayerStylesFilter::TransformBounds(filterBounds, filterList); + } } void FilterRenderer::MeasureFilterBounds(Rect* bounds, const FilterModifier* modifier) { - auto filterList = MakeFilterList(modifier); - if (filterList->processVisibleAreaOnly) { - bounds->roundOut(); - } else { - *bounds = GetParentBounds(filterList.get()); - } - TransformFilterBounds(bounds, filterList.get()); - if (filterList->useParentSizeInput) { - Matrix inverted = Matrix::I(); - filterList->layerMatrix.invert(&inverted); - inverted.mapRect(bounds); - } + auto filterList = MakeFilterList(modifier); + if (filterList->processVisibleAreaOnly) { + bounds->roundOut(); + } else { + *bounds = GetParentBounds(filterList.get()); + } + TransformFilterBounds(bounds, filterList.get()); + if (filterList->useParentSizeInput) { + Matrix inverted = Matrix::I(); + filterList->layerMatrix.invert(&inverted); + inverted.mapRect(bounds); + } } Rect GetClipBounds(Canvas* canvas, const FilterList* filterList) { - auto clip = canvas->getGlobalClip(); - auto matrix = canvas->getMatrix(); - if (filterList->useParentSizeInput) { + auto clip = canvas->getGlobalClip(); + auto matrix = canvas->getMatrix(); + if (filterList->useParentSizeInput) { + Matrix inverted = Matrix::I(); + filterList->layerMatrix.invert(&inverted); + matrix.preConcat(inverted); + } Matrix inverted = Matrix::I(); - filterList->layerMatrix.invert(&inverted); - matrix.preConcat(inverted); - } - Matrix inverted = Matrix::I(); - matrix.invert(&inverted); - clip.transform(inverted); - return clip.getBounds(); + matrix.invert(&inverted); + clip.transform(inverted); + return clip.getBounds(); } std::shared_ptr GetDisplacementMapGraphic(const FilterList* filterList, Layer* mapLayer, - Rect* mapBounds) { - // DisplacementMap只支持引用视频序列帧或者位图序列帧图层。 - // TODO(domrjchen): DisplacementMap 支持所有图层 - auto preComposeLayer = static_cast(mapLayer); - auto composition = preComposeLayer->composition; - mapBounds->setXYWH(0, 0, static_cast(composition->width), - static_cast(composition->height)); - auto contentFrame = filterList->layerFrame - mapLayer->startTime; - auto layerCache = LayerCache::Get(mapLayer); - auto content = layerCache->getContent(contentFrame); - return static_cast(content)->graphic; + Rect* mapBounds) { + // DisplacementMap只支持引用视频序列帧或者位图序列帧图层。 + // TODO(domrjchen): DisplacementMap 支持所有图层 + auto preComposeLayer = static_cast(mapLayer); + auto composition = preComposeLayer->composition; + mapBounds->setXYWH(0, 0, static_cast(composition->width), + static_cast(composition->height)); + auto contentFrame = filterList->layerFrame - mapLayer->startTime; + auto layerCache = LayerCache::Get(mapLayer); + auto content = layerCache->getContent(contentFrame); + return static_cast(content)->graphic; } static bool MakeLayerStyleNode(std::vector& filterNodes, Rect& clipBounds, const FilterList* filterList, RenderCache* renderCache, Rect& filterBounds) { - if (!filterList->layerStyles.empty()) { - auto filter = renderCache->getLayerStylesFilter(filterList->layer); - if (nullptr == filter) { - return false; - } - auto layerStyleScale = filterList->layerStyleScale; - auto oldBounds = filterBounds; - LayerStylesFilter::TransformBounds(&filterBounds, filterList); - filterBounds.roundOut(); - filter->update(filterList, oldBounds, filterBounds, layerStyleScale); - if (!filterBounds.intersect(clipBounds)) { - return false; - } - filterNodes.emplace_back(filter, filterBounds); - } - return true; + if (!filterList->layerStyles.empty()) { + auto filter = renderCache->getLayerStylesFilter(filterList->layer); + if (nullptr == filter) { + return false; + } + auto layerStyleScale = filterList->layerStyleScale; + auto oldBounds = filterBounds; + LayerStylesFilter::TransformBounds(&filterBounds, filterList); + filterBounds.roundOut(); + filter->update(filterList, oldBounds, filterBounds, layerStyleScale); + if (!filterBounds.intersect(clipBounds)) { + return false; + } + filterNodes.emplace_back(filter, filterBounds); + } + return true; } static bool MakeMotionBlurNode(std::vector& filterNodes, Rect& clipBounds, const FilterList* filterList, RenderCache* renderCache, Rect& filterBounds, Point& effectScale) { - if (filterList->layer->motionBlur) { - auto filter = renderCache->getMotionBlurFilter(); - if (filter && filter->updateLayer(filterList->layer, filterList->layerFrame)) { - auto oldBounds = filterBounds; - MotionBlurFilter::TransformBounds(&filterBounds, effectScale, filterList->layer, - filterList->layerFrame); - filterBounds.roundOut(); - filter->update(filterList->layerFrame, oldBounds, filterBounds, effectScale); - if (!filterBounds.intersect(clipBounds)) { - return false; - } - filterNodes.emplace_back(filter, filterBounds); - } - } - return true; + if (filterList->layer->motionBlur) { + auto filter = renderCache->getMotionBlurFilter(); + if (filter && filter->updateLayer(filterList->layer, filterList->layerFrame)) { + auto oldBounds = filterBounds; + MotionBlurFilter::TransformBounds(&filterBounds, effectScale, filterList->layer, + filterList->layerFrame); + filterBounds.roundOut(); + filter->update(filterList->layerFrame, oldBounds, filterBounds, effectScale); + if (!filterBounds.intersect(clipBounds)) { + return false; + } + filterNodes.emplace_back(filter, filterBounds); + } + } + return true; } bool FilterRenderer::MakeEffectNode(std::vector& filterNodes, Rect& clipBounds, const FilterList* filterList, RenderCache* renderCache, Rect& filterBounds, Point& effectScale, int clipIndex) { - auto effectIndex = 0; - for (auto& effect : filterList->effects) { - auto filter = renderCache->getFilterCache(effect); - if (filter) { - auto oldBounds = filterBounds; - effect->transformBounds(&filterBounds, effectScale, filterList->layerFrame); - filterBounds.roundOut(); - filter->update(filterList->layerFrame, oldBounds, filterBounds, effectScale); - if (effect->type() == EffectType::DisplacementMap) { - auto mapEffect = static_cast(effect); - auto mapFilter = static_cast(filter); - auto mapBounds = Rect::MakeEmpty(); - auto graphic = - GetDisplacementMapGraphic(filterList, mapEffect->displacementMapLayer, &mapBounds); - mapBounds.roundOut(); - mapFilter->updateMapTexture(renderCache, graphic.get(), mapBounds); - } - if (effectIndex >= clipIndex && !filterBounds.intersect(clipBounds)) { - return false; - } - filterNodes.emplace_back(filter, filterBounds); - } - effectIndex++; - } - return true; + auto effectIndex = 0; + for (auto& effect : filterList->effects) { + auto filter = renderCache->getFilterCache(effect); + if (filter) { + auto oldBounds = filterBounds; + effect->transformBounds(&filterBounds, effectScale, filterList->layerFrame); + filterBounds.roundOut(); + filter->update(filterList->layerFrame, oldBounds, filterBounds, effectScale); + if (effect->type() == EffectType::DisplacementMap) { + auto mapEffect = static_cast(effect); + auto mapFilter = static_cast(filter); + auto mapBounds = Rect::MakeEmpty(); + auto graphic = + GetDisplacementMapGraphic(filterList, mapEffect->displacementMapLayer, &mapBounds); + mapBounds.roundOut(); + mapFilter->updateMapTexture(renderCache, graphic.get(), mapBounds); + } + if (effectIndex >= clipIndex && !filterBounds.intersect(clipBounds)) { + return false; + } + filterNodes.emplace_back(filter, filterBounds); + } + effectIndex++; + } + return true; } std::vector FilterRenderer::MakeFilterNodes(const FilterList* filterList, - RenderCache* renderCache, - Rect* contentBounds, const Rect& clipRect) { - // 滤镜应用顺序:Effects->PAGFilter->motionBlur->LayerStyles - std::vector filterNodes = {}; - int clipIndex = -1; - for (int i = static_cast(filterList->effects.size()) - 1; i >= 0; i--) { - auto effect = filterList->effects[i]; - if (!effect->processVisibleAreaOnly()) { - clipIndex = i; - break; - } - } - auto clipBounds = clipRect; - auto filterBounds = *contentBounds; - auto effectScale = filterList->effectScale; - // MotionBlur Fragment Shader中需要用到裁切区域外的像素, - // 因此默认先把裁切区域过一次TransformBounds - if (filterList->layer->motionBlur) { - MotionBlurFilter::TransformBounds(&clipBounds, effectScale, filterList->layer, - filterList->layerFrame); - clipBounds.roundOut(); - } - if (clipIndex == -1 && !contentBounds->intersect(clipBounds)) { - return {}; - } + RenderCache* renderCache, + Rect* contentBounds, const Rect& clipRect) { + // 滤镜应用顺序:Effects->PAGFilter->motionBlur->LayerStyles + std::vector filterNodes = {}; + int clipIndex = -1; + for (int i = static_cast(filterList->effects.size()) - 1; i >= 0; i--) { + auto effect = filterList->effects[i]; + if (!effect->processVisibleAreaOnly()) { + clipIndex = i; + break; + } + } + auto clipBounds = clipRect; + auto filterBounds = *contentBounds; + auto effectScale = filterList->effectScale; + // MotionBlur Fragment Shader中需要用到裁切区域外的像素, + // 因此默认先把裁切区域过一次TransformBounds + if (filterList->layer->motionBlur) { + MotionBlurFilter::TransformBounds(&clipBounds, effectScale, filterList->layer, + filterList->layerFrame); + clipBounds.roundOut(); + } + if (clipIndex == -1 && !contentBounds->intersect(clipBounds)) { + return {}; + } - if (!MakeEffectNode(filterNodes, clipBounds, filterList, renderCache, filterBounds, effectScale, - clipIndex)) { - return {}; - } + if (!MakeEffectNode(filterNodes, clipBounds, filterList, renderCache, filterBounds, effectScale, + clipIndex)) { + return {}; + } - if (!MakeMotionBlurNode(filterNodes, clipBounds, filterList, renderCache, filterBounds, - effectScale)) { - return {}; - } + if (!MakeMotionBlurNode(filterNodes, clipBounds, filterList, renderCache, filterBounds, + effectScale)) { + return {}; + } - if (!MakeLayerStyleNode(filterNodes, clipBounds, filterList, renderCache, filterBounds)) { - return {}; - } - return filterNodes; + if (!MakeLayerStyleNode(filterNodes, clipBounds, filterList, renderCache, filterBounds)) { + return {}; + } + return filterNodes; } void ApplyFilters(Context* context, std::vector filterNodes, const Rect& contentBounds, FilterSource* filterSource, FilterTarget* filterTarget) { - GLStateGuard stateGuard(context); - auto gl = GLContext::Unwrap(context); - auto scale = filterSource->scale; - std::shared_ptr freeBuffer = nullptr; - std::shared_ptr lastBuffer = nullptr; - std::shared_ptr lastSource = nullptr; - auto lastBounds = contentBounds; - auto lastUsesMSAA = false; - auto size = static_cast(filterNodes.size()); - for (int i = 0; i < size; i++) { - auto& node = filterNodes[i]; - auto source = lastSource == nullptr ? filterSource : lastSource.get(); - if (i == size - 1) { - node.filter->draw(context, source, filterTarget); - break; - } - std::shared_ptr currentBuffer = nullptr; - if (freeBuffer && node.bounds.width() == lastBounds.width() && - node.bounds.height() == lastBounds.height() && node.filter->needsMSAA() == lastUsesMSAA) { - currentBuffer = freeBuffer; - } else { - currentBuffer = FilterBuffer::Make( - context, static_cast(ceilf(node.bounds.width() * scale.x)), - static_cast(ceilf(node.bounds.height() * scale.y)), node.filter->needsMSAA()); - } - if (currentBuffer == nullptr) { - return; - } - currentBuffer->clearColor(gl); - auto offsetMatrix = Matrix::MakeTrans((lastBounds.left - node.bounds.left) * scale.x, - (lastBounds.top - node.bounds.top) * scale.y); - auto currentTarget = currentBuffer->toFilterTarget(offsetMatrix); - node.filter->draw(context, source, currentTarget.get()); - currentBuffer->resolve(context); - lastSource = currentBuffer->toFilterSource(scale); - freeBuffer = lastBuffer; - lastBuffer = currentBuffer; - lastBounds = node.bounds; - lastUsesMSAA = currentBuffer->usesMSAA(); - } + GLStateGuard stateGuard(context); + auto gl = GLContext::Unwrap(context); + auto scale = filterSource->scale; + std::shared_ptr freeBuffer = nullptr; + std::shared_ptr lastBuffer = nullptr; + std::shared_ptr lastSource = nullptr; + auto lastBounds = contentBounds; + auto lastUsesMSAA = false; + auto size = static_cast(filterNodes.size()); + for (int i = 0; i < size; i++) { + auto& node = filterNodes[i]; + auto source = lastSource == nullptr ? filterSource : lastSource.get(); + if (i == size - 1) { + node.filter->draw(context, source, filterTarget); + break; + } + std::shared_ptr currentBuffer = nullptr; + if (freeBuffer && node.bounds.width() == lastBounds.width() && + node.bounds.height() == lastBounds.height() && node.filter->needsMSAA() == lastUsesMSAA) { + currentBuffer = freeBuffer; + } else { + currentBuffer = FilterBuffer::Make( + context, static_cast(ceilf(node.bounds.width() * scale.x)), + static_cast(ceilf(node.bounds.height() * scale.y)), node.filter->needsMSAA()); + } + if (currentBuffer == nullptr) { + return; + } + currentBuffer->clearColor(gl); + auto offsetMatrix = Matrix::MakeTrans((lastBounds.left - node.bounds.left) * scale.x, + (lastBounds.top - node.bounds.top) * scale.y); + auto currentTarget = currentBuffer->toFilterTarget(offsetMatrix); + node.filter->draw(context, source, currentTarget.get()); + currentBuffer->resolve(context); + lastSource = currentBuffer->toFilterSource(scale); + freeBuffer = lastBuffer; + lastBuffer = currentBuffer; + lastBounds = node.bounds; + lastUsesMSAA = currentBuffer->usesMSAA(); + } } std::unique_ptr GetDirectFilterTarget(Canvas* parentCanvas, - const FilterList* filterList, - const std::vector& filterNodes, - const Rect& contentBounds, - const Point& sourceScale) { - // 在高分辨率下,模糊滤镜的开销会增大,需要降采样降低开销;当模糊为最后一个滤镜时,需要离屏绘制 - if (!filterList->effects.empty() && filterList->effects.back()->type() == EffectType::FastBlur) { - return nullptr; - } - if (filterNodes.back().filter->needsMSAA()) { - return nullptr; - } - // 是否能直接上屏,应该用没有经过裁切的transformBounds来判断, - // 因为计算filter的顶点位置的bounds都是没有经过裁切的 - auto transformBounds = contentBounds; - TransformFilterBounds(&transformBounds, filterList); - if (parentCanvas->hasComplexPaint(transformBounds) != PaintKind::None) { - return nullptr; - } - auto surface = parentCanvas->getSurface(); - auto totalMatrix = parentCanvas->getMatrix(); - if (totalMatrix.getSkewX() != 0 || totalMatrix.getSkewY() != 0) { - return nullptr; - } - auto secondToLastBounds = - filterNodes.size() > 1 ? filterNodes[filterNodes.size() - 2].bounds : contentBounds; - totalMatrix.preTranslate(secondToLastBounds.left, secondToLastBounds.top); - totalMatrix.preScale(1.0f / sourceScale.x, 1.0f / sourceScale.y); - return ToFilterTarget(surface, totalMatrix); + const FilterList* filterList, + const std::vector& filterNodes, + const Rect& contentBounds, + const Point& sourceScale) { + // 在高分辨率下,模糊滤镜的开销会增大,需要降采样降低开销;当模糊为最后一个滤镜时,需要离屏绘制 + if (!filterList->effects.empty() && filterList->effects.back()->type() == EffectType::FastBlur) { + return nullptr; + } + if (filterNodes.back().filter->needsMSAA()) { + return nullptr; + } + // 是否能直接上屏,应该用没有经过裁切的transformBounds来判断, + // 因为计算filter的顶点位置的bounds都是没有经过裁切的 + auto transformBounds = contentBounds; + TransformFilterBounds(&transformBounds, filterList); + if (parentCanvas->hasComplexPaint(transformBounds) != PaintKind::None) { + return nullptr; + } + auto surface = parentCanvas->getSurface(); + auto totalMatrix = parentCanvas->getMatrix(); + if (totalMatrix.getSkewX() != 0 || totalMatrix.getSkewY() != 0) { + return nullptr; + } + auto secondToLastBounds = + filterNodes.size() > 1 ? filterNodes[filterNodes.size() - 2].bounds : contentBounds; + totalMatrix.preTranslate(secondToLastBounds.left, secondToLastBounds.top); + totalMatrix.preScale(1.0f / sourceScale.x, 1.0f / sourceScale.y); + return ToFilterTarget(surface, totalMatrix); } std::unique_ptr GetOffscreenFilterTarget(Surface* surface, - const std::vector& filterNodes, - const Rect& contentBounds, - const Point& sourceScale) { - auto finalBounds = filterNodes.back().bounds; - auto secondToLastBounds = - filterNodes.size() > 1 ? filterNodes[filterNodes.size() - 2].bounds : contentBounds; - auto totalMatrix = Matrix::MakeTrans((secondToLastBounds.left - finalBounds.left) * sourceScale.x, - (secondToLastBounds.top - finalBounds.top) * sourceScale.y); - return ToFilterTarget(surface, totalMatrix); + const std::vector& filterNodes, + const Rect& contentBounds, + const Point& sourceScale) { + auto finalBounds = filterNodes.back().bounds; + auto secondToLastBounds = + filterNodes.size() > 1 ? filterNodes[filterNodes.size() - 2].bounds : contentBounds; + auto totalMatrix = Matrix::MakeTrans((secondToLastBounds.left - finalBounds.left) * sourceScale.x, + (secondToLastBounds.top - finalBounds.top) * sourceScale.y); + return ToFilterTarget(surface, totalMatrix); } std::unique_ptr ToFilterSource(Canvas* canvas) { - auto surface = canvas->getSurface(); - auto texture = surface->getTexture(); - Point scale = {}; - scale.x = scale.y = GetMaxScaleFactor(canvas->getMatrix()); - return ToFilterSource(texture.get(), scale); + auto surface = canvas->getSurface(); + auto texture = surface->getTexture(); + Point scale = {}; + scale.x = scale.y = GetMaxScaleFactor(canvas->getMatrix()); + return ToFilterSource(texture.get(), scale); } void FilterRenderer::ProcessFastBlur(FilterList* filterList) { - // 注意:含有layerStyle的情况下,不能走SingleImage的优化模式,因为目前DropShadowFilter还不是shader模式, - // 无法实现textureMatrix的绘制,等DropShadowFilter改为shader模式后去掉这个限制。 - // 在高分辨率下,模糊滤镜的开销会增大,需要降采样降低开销;当模糊为最后一个滤镜时,需要离屏绘制 - for (auto effect : filterList->effects) { - if (effect->type() == EffectType::FastBlur) { - auto blurEffect = static_cast(effect); - // 当模糊度不变化时,使用缩放提高性能 - if (!blurEffect->blurriness->animatable()) { - filterList->scaleFactorLimit = FAST_BLUR_MAX_SCALE_FACTOR; - } - break; - } - } + // 注意:含有layerStyle的情况下,不能走SingleImage的优化模式,因为目前DropShadowFilter还不是shader模式, + // 无法实现textureMatrix的绘制,等DropShadowFilter改为shader模式后去掉这个限制。 + // 在高分辨率下,模糊滤镜的开销会增大,需要降采样降低开销;当模糊为最后一个滤镜时,需要离屏绘制 + for (auto effect : filterList->effects) { + if (effect->type() == EffectType::FastBlur) { + auto blurEffect = static_cast(effect); + // 当模糊度不变化时,使用缩放提高性能 + if (!blurEffect->blurriness->animatable()) { + filterList->scaleFactorLimit = FAST_BLUR_MAX_SCALE_FACTOR; + } + break; + } + } } void FilterRenderer::DrawWithFilter(Canvas* parentCanvas, RenderCache* cache, const FilterModifier* modifier, std::shared_ptr content) { - auto filterList = MakeFilterList(modifier); - auto contentBounds = GetContentBounds(filterList.get(), content); - // 相对于content Bounds的clip Bounds - auto clipBounds = GetClipBounds(parentCanvas, filterList.get()); - auto filterNodes = MakeFilterNodes(filterList.get(), cache, &contentBounds, clipBounds); - if (filterNodes.empty()) { - content->draw(parentCanvas, cache); - return; - } - if (filterList->useParentSizeInput) { - Matrix inverted = Matrix::I(); - filterList->layerMatrix.invert(&inverted); - parentCanvas->concat(inverted); - } - ProcessFastBlur(filterList.get()); - auto contentSurface = - parentCanvas->makeContentSurface(contentBounds, filterList->scaleFactorLimit); - if (contentSurface == nullptr) { - return; - } - auto contentCanvas = contentSurface->getCanvas(); - if (filterList->useParentSizeInput) { - contentCanvas->concat(filterList->layerMatrix); - } - content->draw(contentCanvas, cache); - auto filterSource = ToFilterSource(contentCanvas); - std::shared_ptr targetSurface = nullptr; - std::unique_ptr filterTarget = GetDirectFilterTarget( - parentCanvas, filterList.get(), filterNodes, contentBounds, filterSource->scale); - if (filterTarget == nullptr) { - // 需要离屏绘制 - targetSurface = - parentCanvas->makeContentSurface(filterNodes.back().bounds, filterList->scaleFactorLimit, - filterNodes.back().filter->needsMSAA()); - if (targetSurface == nullptr) { - return; - } - filterTarget = GetOffscreenFilterTarget(targetSurface.get(), filterNodes, contentBounds, - filterSource->scale); - } + auto filterList = MakeFilterList(modifier); + auto contentBounds = GetContentBounds(filterList.get(), content); + // 相对于content Bounds的clip Bounds + auto clipBounds = GetClipBounds(parentCanvas, filterList.get()); + auto filterNodes = MakeFilterNodes(filterList.get(), cache, &contentBounds, clipBounds); + if (filterNodes.empty()) { + content->draw(parentCanvas, cache); + return; + } + if (filterList->useParentSizeInput) { + Matrix inverted = Matrix::I(); + filterList->layerMatrix.invert(&inverted); + parentCanvas->concat(inverted); + } + ProcessFastBlur(filterList.get()); + auto contentSurface = + parentCanvas->makeContentSurface(contentBounds, filterList->scaleFactorLimit); + if (contentSurface == nullptr) { + return; + } + auto contentCanvas = contentSurface->getCanvas(); + if (filterList->useParentSizeInput) { + contentCanvas->concat(filterList->layerMatrix); + } + content->draw(contentCanvas, cache); + auto filterSource = ToFilterSource(contentCanvas); + std::shared_ptr targetSurface = nullptr; + std::unique_ptr filterTarget = GetDirectFilterTarget( + parentCanvas, filterList.get(), filterNodes, contentBounds, filterSource->scale); + if (filterTarget == nullptr) { + // 需要离屏绘制 + targetSurface = + parentCanvas->makeContentSurface(filterNodes.back().bounds, filterList->scaleFactorLimit, + filterNodes.back().filter->needsMSAA()); + if (targetSurface == nullptr) { + return; + } + filterTarget = GetOffscreenFilterTarget(targetSurface.get(), filterNodes, contentBounds, + filterSource->scale); + } - // 必须要flush,要不然framebuffer还没真正画到canvas,就被其他图层的filter串改了该framebuffer - parentCanvas->flush(); - auto context = parentCanvas->getContext(); - ApplyFilters(context, filterNodes, contentBounds, filterSource.get(), filterTarget.get()); + // 必须要flush,要不然framebuffer还没真正画到canvas,就被其他图层的filter串改了该framebuffer + parentCanvas->flush(); + auto context = parentCanvas->getContext(); + ApplyFilters(context, filterNodes, contentBounds, filterSource.get(), filterTarget.get()); - if (targetSurface) { - Matrix drawingMatrix = {}; - auto targetCanvas = targetSurface->getCanvas(); - if (!targetCanvas->getMatrix().invert(&drawingMatrix)) { - drawingMatrix.setIdentity(); - } - auto targetTexture = targetSurface->getTexture(); - parentCanvas->drawTexture(targetTexture.get(), drawingMatrix); - } + if (targetSurface) { + Matrix drawingMatrix = {}; + auto targetCanvas = targetSurface->getCanvas(); + if (!targetCanvas->getMatrix().invert(&drawingMatrix)) { + drawingMatrix.setIdentity(); + } + auto targetTexture = targetSurface->getTexture(); + parentCanvas->drawTexture(targetTexture.get(), drawingMatrix); + } } } // namespace pag diff --git a/src/rendering/renderers/FilterRenderer.h b/src/rendering/renderers/FilterRenderer.h index ad3f12a396..dd2c61e437 100644 --- a/src/rendering/renderers/FilterRenderer.h +++ b/src/rendering/renderers/FilterRenderer.h @@ -26,48 +26,48 @@ namespace pag { struct FilterNode { - FilterNode(Filter* filter, const Rect& bounds) : filter(filter), bounds(bounds) { - } + FilterNode(Filter* filter, const Rect& bounds) : filter(filter), bounds(bounds) { + } - Filter* filter; - Rect bounds; + Filter* filter; + Rect bounds; }; struct FilterList { - Layer* layer = nullptr; - Frame layerFrame = 0; - Matrix layerMatrix = Matrix::I(); - float scaleFactorLimit = FLT_MAX; - bool processVisibleAreaOnly = true; - // 是否使用父级Composition容器的尺寸作为滤镜输入源。 - bool useParentSizeInput = false; - Point effectScale = {1.0f, 1.0f}; - Point layerStyleScale = {1.0f, 1.0f}; - std::vector effects = {}; - std::vector layerStyles = {}; + Layer* layer = nullptr; + Frame layerFrame = 0; + Matrix layerMatrix = Matrix::I(); + float scaleFactorLimit = FLT_MAX; + bool processVisibleAreaOnly = true; + // 是否使用父级Composition容器的尺寸作为滤镜输入源。 + bool useParentSizeInput = false; + Point effectScale = {1.0f, 1.0f}; + Point layerStyleScale = {1.0f, 1.0f}; + std::vector effects = {}; + std::vector layerStyles = {}; }; class FilterRenderer { - public: - static void MeasureFilterBounds(Rect* bounds, const FilterModifier* modifier); +public: + static void MeasureFilterBounds(Rect* bounds, const FilterModifier* modifier); - static void DrawWithFilter(Canvas* parentCanvas, RenderCache* cache, - const FilterModifier* modifier, std::shared_ptr content); - static void ProcessFastBlur(FilterList* filterList); + static void DrawWithFilter(Canvas* parentCanvas, RenderCache* cache, + const FilterModifier* modifier, std::shared_ptr content); + static void ProcessFastBlur(FilterList* filterList); - private: - static std::unique_ptr MakeFilterList(const FilterModifier* modifier); +private: + static std::unique_ptr MakeFilterList(const FilterModifier* modifier); - static Rect GetParentBounds(const FilterList* filterList); + static Rect GetParentBounds(const FilterList* filterList); - static Rect GetContentBounds(const FilterList* filterList, std::shared_ptr content); + static Rect GetContentBounds(const FilterList* filterList, std::shared_ptr content); - static bool MakeEffectNode(std::vector& filterNodes, Rect& clipBounds, - const FilterList* filterList, RenderCache* renderCache, - Rect& filterBounds, Point& effectScale, int clipIndex); + static bool MakeEffectNode(std::vector& filterNodes, Rect& clipBounds, + const FilterList* filterList, RenderCache* renderCache, + Rect& filterBounds, Point& effectScale, int clipIndex); - static std::vector MakeFilterNodes(const FilterList* filterList, - RenderCache* renderCache, Rect* contentBounds, - const Rect& clipRect); + static std::vector MakeFilterNodes(const FilterList* filterList, + RenderCache* renderCache, Rect* contentBounds, + const Rect& clipRect); }; } // namespace pag \ No newline at end of file diff --git a/src/rendering/renderers/LayerRenderer.cpp b/src/rendering/renderers/LayerRenderer.cpp index 1857de5252..a683297212 100644 --- a/src/rendering/renderers/LayerRenderer.cpp +++ b/src/rendering/renderers/LayerRenderer.cpp @@ -24,110 +24,110 @@ namespace pag { static bool TransformIllegal(Transform* transform) { - return transform && !transform->visible(); + return transform && !transform->visible(); } static bool TrackMatteIsEmpty(TrackMatte* trackMatte) { - if (trackMatte == nullptr) { - return false; - } - return trackMatte->modifier->isEmpty(); + if (trackMatte == nullptr) { + return false; + } + return trackMatte->modifier->isEmpty(); } void LayerRenderer::DrawLayer(Recorder* recorder, Layer* layer, Frame layerFrame, std::shared_ptr filterModifier, TrackMatte* trackMatte, Content* layerContent, Transform* extraTransform) { - if (TransformIllegal(extraTransform) || TrackMatteIsEmpty(trackMatte)) { - return; - } - auto contentFrame = layerFrame - layer->startTime; - auto layerCache = LayerCache::Get(layer); - if (!layerCache->contentVisible(contentFrame)) { - return; - } - auto content = layerContent ? layerContent : layerCache->getContent(contentFrame); - auto layerTransform = layerCache->getTransform(contentFrame); - auto opacity = layerTransform->opacity; - if (extraTransform) { - opacity = OpacityConcat(opacity, extraTransform->opacity); - } - recorder->saveLayer(opacity, layer->blendMode); - if (trackMatte) { - recorder->saveLayer(trackMatte->modifier); - } - auto saveCount = recorder->getSaveCount(); - if (extraTransform) { - recorder->concat(extraTransform->matrix); - } - recorder->concat(layerTransform->matrix); - if (filterModifier) { - recorder->saveLayer(filterModifier); - } - auto masks = layerCache->getMasks(contentFrame); - if (masks) { - recorder->saveClip(*masks); - } - content->draw(recorder); - recorder->restoreToCount(saveCount); - if (trackMatte) { + if (TransformIllegal(extraTransform) || TrackMatteIsEmpty(trackMatte)) { + return; + } + auto contentFrame = layerFrame - layer->startTime; + auto layerCache = LayerCache::Get(layer); + if (!layerCache->contentVisible(contentFrame)) { + return; + } + auto content = layerContent ? layerContent : layerCache->getContent(contentFrame); + auto layerTransform = layerCache->getTransform(contentFrame); + auto opacity = layerTransform->opacity; + if (extraTransform) { + opacity = OpacityConcat(opacity, extraTransform->opacity); + } + recorder->saveLayer(opacity, layer->blendMode); + if (trackMatte) { + recorder->saveLayer(trackMatte->modifier); + } + auto saveCount = recorder->getSaveCount(); + if (extraTransform) { + recorder->concat(extraTransform->matrix); + } + recorder->concat(layerTransform->matrix); + if (filterModifier) { + recorder->saveLayer(filterModifier); + } + auto masks = layerCache->getMasks(contentFrame); + if (masks) { + recorder->saveClip(*masks); + } + content->draw(recorder); + recorder->restoreToCount(saveCount); + if (trackMatte) { + recorder->restore(); + // 若遮罩图层是文本图层,对内部自带颜色的字符(如 emoji )多执行一次叠加的绘制, + // 让自带颜色的字符能正常显示出来。 + recorder->drawGraphic(trackMatte->colorGlyphs); + } recorder->restore(); - // 若遮罩图层是文本图层,对内部自带颜色的字符(如 emoji )多执行一次叠加的绘制, - // 让自带颜色的字符能正常显示出来。 - recorder->drawGraphic(trackMatte->colorGlyphs); - } - recorder->restore(); } static void ApplyClipToBounds(const Path& clipPath, Rect* bounds) { - if (!clipPath.isInverseFillType()) { - auto clipBounds = clipPath.getBounds(); - if (!bounds->intersect(clipBounds)) { - bounds->setEmpty(); - } - return; - } - Path boundsPath = {}; - boundsPath.addRect(*bounds); - boundsPath.addPath(clipPath, PathOp::Intersect); - *bounds = boundsPath.getBounds(); + if (!clipPath.isInverseFillType()) { + auto clipBounds = clipPath.getBounds(); + if (!bounds->intersect(clipBounds)) { + bounds->setEmpty(); + } + return; + } + Path boundsPath = {}; + boundsPath.addRect(*bounds); + boundsPath.addPath(clipPath, PathOp::Intersect); + *bounds = boundsPath.getBounds(); } static bool boundsIsEmpty(Rect* bounds) { - return bounds && bounds->isEmpty(); + return bounds && bounds->isEmpty(); } void LayerRenderer::MeasureLayerBounds(Rect* bounds, Layer* layer, Frame layerFrame, std::shared_ptr filterModifier, Rect* trackMatteBounds, Content* layerContent, Transform* extraTransform) { - bounds->setEmpty(); - if (TransformIllegal(extraTransform) || boundsIsEmpty(trackMatteBounds)) { - return; - } - auto contentFrame = layerFrame - layer->startTime; - auto layerCache = LayerCache::Get(layer); - if (!layerCache->contentVisible(contentFrame)) { - return; - } - auto content = layerContent ? layerContent : layerCache->getContent(contentFrame); - auto masks = layerCache->getMasks(contentFrame); - content->measureBounds(bounds); - if (masks) { - ApplyClipToBounds(*masks, bounds); - } - if (filterModifier) { - FilterRenderer::MeasureFilterBounds(bounds, filterModifier.get()); - } - auto layerMatrix = layerCache->getTransform(contentFrame)->matrix; - if (extraTransform) { - layerMatrix.postConcat(extraTransform->matrix); - } - layerMatrix.mapRect(bounds); - if (trackMatteBounds != nullptr) { - if (!bounds->intersect(*trackMatteBounds)) { - bounds->setEmpty(); - } - } + bounds->setEmpty(); + if (TransformIllegal(extraTransform) || boundsIsEmpty(trackMatteBounds)) { + return; + } + auto contentFrame = layerFrame - layer->startTime; + auto layerCache = LayerCache::Get(layer); + if (!layerCache->contentVisible(contentFrame)) { + return; + } + auto content = layerContent ? layerContent : layerCache->getContent(contentFrame); + auto masks = layerCache->getMasks(contentFrame); + content->measureBounds(bounds); + if (masks) { + ApplyClipToBounds(*masks, bounds); + } + if (filterModifier) { + FilterRenderer::MeasureFilterBounds(bounds, filterModifier.get()); + } + auto layerMatrix = layerCache->getTransform(contentFrame)->matrix; + if (extraTransform) { + layerMatrix.postConcat(extraTransform->matrix); + } + layerMatrix.mapRect(bounds); + if (trackMatteBounds != nullptr) { + if (!bounds->intersect(*trackMatteBounds)) { + bounds->setEmpty(); + } + } } } // namespace pag diff --git a/src/rendering/renderers/LayerRenderer.h b/src/rendering/renderers/LayerRenderer.h index f4cb9380a9..ada5f5b152 100644 --- a/src/rendering/renderers/LayerRenderer.h +++ b/src/rendering/renderers/LayerRenderer.h @@ -23,16 +23,16 @@ namespace pag { class LayerRenderer { - public: - static void DrawLayer(Recorder* recorder, Layer* layer, Frame layerFrame, - std::shared_ptr filterModifier = nullptr, - TrackMatte* trackMatte = nullptr, Content* layerContent = nullptr, - Transform* extraTransform = nullptr); +public: + static void DrawLayer(Recorder* recorder, Layer* layer, Frame layerFrame, + std::shared_ptr filterModifier = nullptr, + TrackMatte* trackMatte = nullptr, Content* layerContent = nullptr, + Transform* extraTransform = nullptr); - static void MeasureLayerBounds(Rect* bounds, Layer* layer, Frame layerFrame, - std::shared_ptr filterModifier = nullptr, - Rect* trackMatteBounds = nullptr, Content* content = nullptr, - Transform* extraTransform = nullptr); + static void MeasureLayerBounds(Rect* bounds, Layer* layer, Frame layerFrame, + std::shared_ptr filterModifier = nullptr, + Rect* trackMatteBounds = nullptr, Content* content = nullptr, + Transform* extraTransform = nullptr); }; } // namespace pag diff --git a/src/rendering/renderers/MaskRenderer.cpp b/src/rendering/renderers/MaskRenderer.cpp index b01e65ec09..3b9f64cd3e 100644 --- a/src/rendering/renderers/MaskRenderer.cpp +++ b/src/rendering/renderers/MaskRenderer.cpp @@ -23,61 +23,61 @@ namespace pag { PathOp ToPathOp(Enum maskMode) { - switch (maskMode) { + switch (maskMode) { case MaskMode::Subtract: - return PathOp::Difference; + return PathOp::Difference; case MaskMode::Intersect: - return PathOp::Intersect; + return PathOp::Intersect; case MaskMode::Difference: - return PathOp::XOR; + return PathOp::XOR; case MaskMode::Darken: // without the opacity blending, haven't supported it - return PathOp::Intersect; + return PathOp::Intersect; default: - return PathOp::Union; - } + return PathOp::Union; + } } static void ExpandPath(Path* path, float expansion) { - if (expansion == 0) { - return; - } - auto strokePath = *path; - auto effect = PathEffect::MakeStroke(Stroke(fabsf(expansion) * 2)); - if (effect) { - effect->applyTo(&strokePath); - } - if (expansion < 0) { - path->addPath(strokePath, PathOp::Difference); - } else { - path->addPath(strokePath, PathOp::Union); - } -} - -void RenderMasks(Path* maskContent, const std::vector& masks, Frame layerFrame) { - bool isFirst = true; - for (auto& mask : masks) { - auto path = mask->maskPath->getValueAt(layerFrame); - if (path == nullptr || !path->isClosed() || mask->maskMode == MaskMode::None) { - continue; - } - auto maskPath = ToPath(*path); - auto expansion = mask->maskExpansion->getValueAt(layerFrame); - ExpandPath(&maskPath, expansion); - auto inverted = mask->inverted; - if (isFirst) { - if (mask->maskMode == MaskMode::Subtract) { - inverted = !inverted; - } + if (expansion == 0) { + return; } - if (inverted) { - maskPath.toggleInverseFillType(); + auto strokePath = *path; + auto effect = PathEffect::MakeStroke(Stroke(fabsf(expansion) * 2)); + if (effect) { + effect->applyTo(&strokePath); } - if (isFirst) { - isFirst = false; - *maskContent = maskPath; + if (expansion < 0) { + path->addPath(strokePath, PathOp::Difference); } else { - maskContent->addPath(maskPath, ToPathOp(mask->maskMode)); + path->addPath(strokePath, PathOp::Union); + } +} + +void RenderMasks(Path* maskContent, const std::vector& masks, Frame layerFrame) { + bool isFirst = true; + for (auto& mask : masks) { + auto path = mask->maskPath->getValueAt(layerFrame); + if (path == nullptr || !path->isClosed() || mask->maskMode == MaskMode::None) { + continue; + } + auto maskPath = ToPath(*path); + auto expansion = mask->maskExpansion->getValueAt(layerFrame); + ExpandPath(&maskPath, expansion); + auto inverted = mask->inverted; + if (isFirst) { + if (mask->maskMode == MaskMode::Subtract) { + inverted = !inverted; + } + } + if (inverted) { + maskPath.toggleInverseFillType(); + } + if (isFirst) { + isFirst = false; + *maskContent = maskPath; + } else { + maskContent->addPath(maskPath, ToPathOp(mask->maskMode)); + } } - } } } // namespace pag diff --git a/src/rendering/renderers/ShapeRenderer.cpp b/src/rendering/renderers/ShapeRenderer.cpp index aee797b77d..409e970865 100644 --- a/src/rendering/renderers/ShapeRenderer.cpp +++ b/src/rendering/renderers/ShapeRenderer.cpp @@ -33,11 +33,11 @@ namespace pag { enum class ElementDataType { Paint, Path, Group }; class ElementData { - public: - virtual ~ElementData() = default; - virtual ElementDataType type() const = 0; - virtual std::unique_ptr clone() = 0; - virtual void applyMatrix(const Matrix& matrix) = 0; +public: + virtual ~ElementData() = default; + virtual ElementDataType type() const = 0; + virtual std::unique_ptr clone() = 0; + virtual void applyMatrix(const Matrix& matrix) = 0; }; enum class PaintType { Fill, Stroke, GradientFill, GradientStroke }; @@ -46,707 +46,709 @@ enum class PaintType { Fill, Stroke, GradientFill, GradientStroke }; * Defines attributes for drawing strokes. */ struct StrokePaint { - Stroke getStroke() const { - return Stroke(strokeWidth, lineCap, lineJoin, miterLimit); - } - - float strokeWidth; - Enum lineCap; - Enum lineJoin; - float miterLimit; - std::vector dashes; - float dashOffset; + Stroke getStroke() const { + return Stroke(strokeWidth, lineCap, lineJoin, miterLimit); + } + + float strokeWidth; + Enum lineCap; + Enum lineJoin; + float miterLimit; + std::vector dashes; + float dashOffset; }; class PaintElement : public ElementData { - public: - explicit PaintElement(PaintType paintType) : paintType(paintType) { - } - - ElementDataType type() const override { - return ElementDataType::Paint; - } - - std::unique_ptr clone() override { - auto newPaint = new PaintElement(paintType); - newPaint->blendMode = blendMode; - newPaint->opacity = opacity; - newPaint->color = color; - newPaint->gradient = gradient; - newPaint->stroke = stroke; - newPaint->pathFillType = pathFillType; - newPaint->compositeOrder = compositeOrder; - return std::unique_ptr(newPaint); - } - - void applyMatrix(const Matrix& matrix) override { - if (paintType == PaintType::Fill || paintType == PaintType::GradientFill) { - return; - } - stroke.strokeWidth *= fabsf(matrix.getMaxScale()); - } - - PaintType paintType = PaintType::Fill; - Enum blendMode = BlendMode::Normal; - Opacity opacity = Opaque; - Enum compositeOrder = CompositeOrder::BelowPreviousInSameGroup; - PathFillType pathFillType = PathFillType::Winding; - Color color = White; - GradientPaint gradient; - StrokePaint stroke; +public: + explicit PaintElement(PaintType paintType) : paintType(paintType) { + } + + ElementDataType type() const override { + return ElementDataType::Paint; + } + + std::unique_ptr clone() override { + auto newPaint = new PaintElement(paintType); + newPaint->blendMode = blendMode; + newPaint->opacity = opacity; + newPaint->color = color; + newPaint->gradient = gradient; + newPaint->stroke = stroke; + newPaint->pathFillType = pathFillType; + newPaint->compositeOrder = compositeOrder; + return std::unique_ptr(newPaint); + } + + void applyMatrix(const Matrix& matrix) override { + if (paintType == PaintType::Fill || paintType == PaintType::GradientFill) { + return; + } + stroke.strokeWidth *= fabsf(matrix.getMaxScale()); + } + + PaintType paintType = PaintType::Fill; + Enum blendMode = BlendMode::Normal; + Opacity opacity = Opaque; + Enum compositeOrder = CompositeOrder::BelowPreviousInSameGroup; + PathFillType pathFillType = PathFillType::Winding; + Color color = White; + GradientPaint gradient; + StrokePaint stroke; }; class PathElement : public ElementData { - public: - ElementDataType type() const override { - return ElementDataType::Path; - } - - std::unique_ptr clone() override { - auto newPath = new PathElement(); - newPath->path = path; - return std::unique_ptr(newPath); - } - - void applyMatrix(const Matrix& matrix) override { - path.transform(matrix); - } - - Path path; +public: + ElementDataType type() const override { + return ElementDataType::Path; + } + + std::unique_ptr clone() override { + auto newPath = new PathElement(); + newPath->path = path; + return std::unique_ptr(newPath); + } + + void applyMatrix(const Matrix& matrix) override { + path.transform(matrix); + } + + Path path; }; class GroupElement : public ElementData { - public: - ~GroupElement() override { - for (auto& element : elements) { - delete element; - } - } - - ElementDataType type() const override { - return ElementDataType::Group; - } - - std::unique_ptr clone() override { - auto newGroup = new GroupElement(); - newGroup->blendMode = blendMode; - newGroup->opacity = opacity; - for (auto& data : elements) { - auto element = data->clone().release(); - newGroup->elements.push_back(element); - } - return std::unique_ptr(newGroup); - } - - void applyMatrix(const Matrix& matrix) override { - for (auto& element : elements) { - element->applyMatrix(matrix); - } - } - - std::vector pathList() const { - std::vector list; - for (auto& element : elements) { - switch (element->type()) { - case ElementDataType::Path: { - auto pathElement = reinterpret_cast(element); - list.push_back(&pathElement->path); - } break; - case ElementDataType::Group: { - auto group = reinterpret_cast(element); - auto pathList = group->pathList(); - list.insert(list.end(), pathList.begin(), pathList.end()); - } break; - default: - break; - } - } - return list; - } - - void clear() { - for (auto& element : elements) { - delete element; - } - elements.clear(); - } - - Enum blendMode = BlendMode::Normal; - Opacity opacity = Opaque; - std::vector elements; +public: + ~GroupElement() override { + for (auto& element : elements) { + delete element; + } + } + + ElementDataType type() const override { + return ElementDataType::Group; + } + + std::unique_ptr clone() override { + auto newGroup = new GroupElement(); + newGroup->blendMode = blendMode; + newGroup->opacity = opacity; + for (auto& data : elements) { + auto element = data->clone().release(); + newGroup->elements.push_back(element); + } + return std::unique_ptr(newGroup); + } + + void applyMatrix(const Matrix& matrix) override { + for (auto& element : elements) { + element->applyMatrix(matrix); + } + } + + std::vector pathList() const { + std::vector list; + for (auto& element : elements) { + switch (element->type()) { + case ElementDataType::Path: { + auto pathElement = reinterpret_cast(element); + list.push_back(&pathElement->path); + } + break; + case ElementDataType::Group: { + auto group = reinterpret_cast(element); + auto pathList = group->pathList(); + list.insert(list.end(), pathList.begin(), pathList.end()); + } + break; + default: + break; + } + } + return list; + } + + void clear() { + for (auto& element : elements) { + delete element; + } + elements.clear(); + } + + Enum blendMode = BlendMode::Normal; + Opacity opacity = Opaque; + std::vector elements; }; void RectangleToPath(RectangleElement* rectangle, Path* path, Frame frame) { - auto size = rectangle->size->getValueAt(frame); - auto position = rectangle->position->getValueAt(frame); - auto radius = rectangle->roundness->getValueAt(frame); - auto hw = size.x * 0.5f; - auto hh = size.y * 0.5f; - if (radius > hw) { - radius = hw; - } - if (radius > hh) { - radius = hh; - } - auto rect = - Rect::MakeXYWH(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y); - path->addRoundRect(rect, radius, radius, rectangle->reversed, 2); + auto size = rectangle->size->getValueAt(frame); + auto position = rectangle->position->getValueAt(frame); + auto radius = rectangle->roundness->getValueAt(frame); + auto hw = size.x * 0.5f; + auto hh = size.y * 0.5f; + if (radius > hw) { + radius = hw; + } + if (radius > hh) { + radius = hh; + } + auto rect = + Rect::MakeXYWH(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y); + path->addRoundRect(rect, radius, radius, rectangle->reversed, 2); } void EllipseToPath(EllipseElement* ellipse, Path* path, Frame frame) { - auto size = ellipse->size->getValueAt(frame); - auto position = ellipse->position->getValueAt(frame); - auto rect = - Rect::MakeXYWH(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y); - path->addOval(rect, ellipse->reversed); + auto size = ellipse->size->getValueAt(frame); + auto position = ellipse->position->getValueAt(frame); + auto rect = + Rect::MakeXYWH(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y); + path->addOval(rect, ellipse->reversed); } static void AddCurveToPath(Path* path, float centerX, float centerY, float angleDelta, float dx1, float dy1, float roundness1, float dx2, float dy2, float roundness2) { - auto control1X = dx1 - dy1 * roundness1 * angleDelta + centerX; - auto control1Y = dy1 + dx1 * roundness1 * angleDelta + centerY; - auto control2X = dx2 + dy2 * roundness2 * angleDelta + centerX; - auto control2Y = dy2 - dx2 * roundness2 * angleDelta + centerY; - path->cubicTo(control1X, control1Y, control2X, control2Y, dx2 + centerX, dy2 + centerY); + auto control1X = dx1 - dy1 * roundness1 * angleDelta + centerX; + auto control1Y = dy1 + dx1 * roundness1 * angleDelta + centerY; + auto control2X = dx2 + dy2 * roundness2 * angleDelta + centerX; + auto control2Y = dy2 - dx2 * roundness2 * angleDelta + centerY; + path->cubicTo(control1X, control1Y, control2X, control2Y, dx2 + centerX, dy2 + centerY); } static void ConvertPolyStartToPath(Path* path, float centerX, float centerY, float points, float rotation, float innerRadius, float outerRadius, float innerRoundness, float outerRoundness, bool reversed) { - float direction = reversed ? -1 : 1; - auto angleStep = static_cast(M_PI) / points; - auto currentAngle = (rotation - 90) * static_cast(M_PI) / 180; - auto numPoints = static_cast(ceilf(points)) * 2; - auto decimalPart = points - floorf(points); - int decimalIndex = -2; - if (decimalPart != 0) { - decimalIndex = direction > 0 ? 1 : numPoints - 3; - currentAngle -= angleStep * decimalPart * 2.0f; - } - - // Move to the first point. - auto lastDx = outerRadius * cosf(currentAngle); - auto lastDy = outerRadius * sinf(currentAngle); - path->moveTo(lastDx + centerX, lastDy + centerY); - - auto outerFlag = false; - for (int i = 0; i < numPoints; i++) { - auto radius = outerFlag ? outerRadius : innerRadius; - auto angleDelta = angleStep * direction; - if (i == decimalIndex || i == decimalIndex + 1) { - radius = innerRadius + decimalPart * (radius - innerRadius); - angleDelta *= decimalPart; - } - currentAngle += angleDelta; - auto dx = radius * cosf(currentAngle); - auto dy = radius * sinf(currentAngle); - if (innerRoundness != 0 || outerRoundness != 0) { - float lastRoundness, roundness; - if (outerFlag) { - lastRoundness = innerRoundness; - roundness = outerRoundness; - } else { - lastRoundness = outerRoundness; - roundness = innerRoundness; - } - AddCurveToPath(path, centerX, centerY, angleDelta * 0.5f, lastDx, lastDy, lastRoundness, dx, - dy, roundness); - lastDx = dx; - lastDy = dy; - } else { - path->lineTo(dx + centerX, dy + centerY); + float direction = reversed ? -1 : 1; + auto angleStep = static_cast(M_PI) / points; + auto currentAngle = (rotation - 90) * static_cast(M_PI) / 180; + auto numPoints = static_cast(ceilf(points)) * 2; + auto decimalPart = points - floorf(points); + int decimalIndex = -2; + if (decimalPart != 0) { + decimalIndex = direction > 0 ? 1 : numPoints - 3; + currentAngle -= angleStep * decimalPart * 2.0f; } - outerFlag = !outerFlag; - } - path->close(); + + // Move to the first point. + auto lastDx = outerRadius * cosf(currentAngle); + auto lastDy = outerRadius * sinf(currentAngle); + path->moveTo(lastDx + centerX, lastDy + centerY); + + auto outerFlag = false; + for (int i = 0; i < numPoints; i++) { + auto radius = outerFlag ? outerRadius : innerRadius; + auto angleDelta = angleStep * direction; + if (i == decimalIndex || i == decimalIndex + 1) { + radius = innerRadius + decimalPart * (radius - innerRadius); + angleDelta *= decimalPart; + } + currentAngle += angleDelta; + auto dx = radius * cosf(currentAngle); + auto dy = radius * sinf(currentAngle); + if (innerRoundness != 0 || outerRoundness != 0) { + float lastRoundness, roundness; + if (outerFlag) { + lastRoundness = innerRoundness; + roundness = outerRoundness; + } else { + lastRoundness = outerRoundness; + roundness = innerRoundness; + } + AddCurveToPath(path, centerX, centerY, angleDelta * 0.5f, lastDx, lastDy, lastRoundness, dx, + dy, roundness); + lastDx = dx; + lastDy = dy; + } else { + path->lineTo(dx + centerX, dy + centerY); + } + outerFlag = !outerFlag; + } + path->close(); } static void ConvertPolygonToPath(Path* path, float centerX, float centerY, float points, float rotation, float radius, float roundness, bool reversed) { - auto numPoints = static_cast(floorf(points)); - float direction = reversed ? -1 : 1; - auto angleStep = static_cast(M_PI) * 2 / static_cast(numPoints); - auto currentAngle = (rotation - 90) * static_cast(M_PI) / 180; - - // Move to the first point. - auto lastDx = radius * cosf(currentAngle); - auto lastDy = radius * sinf(currentAngle); - path->moveTo(lastDx + centerX, lastDy + centerY); - - auto outerFlag = false; - for (int i = 0; i < numPoints; i++) { - auto angleDelta = angleStep * direction; - currentAngle += angleDelta; - auto dx = radius * cosf(currentAngle); - auto dy = radius * sinf(currentAngle); - if (roundness != 0) { - AddCurveToPath(path, centerX, centerY, angleDelta * 0.5f, lastDx, lastDy, roundness, dx, dy, - roundness); - lastDx = dx; - lastDy = dy; - } else { - path->lineTo(dx + centerX, dy + centerY); + auto numPoints = static_cast(floorf(points)); + float direction = reversed ? -1 : 1; + auto angleStep = static_cast(M_PI) * 2 / static_cast(numPoints); + auto currentAngle = (rotation - 90) * static_cast(M_PI) / 180; + + // Move to the first point. + auto lastDx = radius * cosf(currentAngle); + auto lastDy = radius * sinf(currentAngle); + path->moveTo(lastDx + centerX, lastDy + centerY); + + auto outerFlag = false; + for (int i = 0; i < numPoints; i++) { + auto angleDelta = angleStep * direction; + currentAngle += angleDelta; + auto dx = radius * cosf(currentAngle); + auto dy = radius * sinf(currentAngle); + if (roundness != 0) { + AddCurveToPath(path, centerX, centerY, angleDelta * 0.5f, lastDx, lastDy, roundness, dx, dy, + roundness); + lastDx = dx; + lastDy = dy; + } else { + path->lineTo(dx + centerX, dy + centerY); + } + outerFlag = !outerFlag; } - outerFlag = !outerFlag; - } - path->close(); + path->close(); } void PolyStarToPath(PolyStarElement* polyStar, Path* path, Frame frame) { - auto points = polyStar->points->getValueAt(frame); - auto position = polyStar->position->getValueAt(frame); - auto rotation = polyStar->rotation->getValueAt(frame); - auto innerRadius = polyStar->innerRadius->getValueAt(frame); - auto outerRadius = polyStar->outerRadius->getValueAt(frame); - auto innerRoundness = polyStar->innerRoundness->getValueAt(frame); - auto outerRoundness = polyStar->outerRoundness->getValueAt(frame); - if (polyStar->polyType == PolyStarType::Star) { - ConvertPolyStartToPath(path, position.x, position.y, points, rotation, innerRadius, outerRadius, - innerRoundness, outerRoundness, polyStar->reversed); - } else { - ConvertPolygonToPath(path, position.x, position.y, points, rotation, outerRadius, - outerRoundness, polyStar->reversed); - } + auto points = polyStar->points->getValueAt(frame); + auto position = polyStar->position->getValueAt(frame); + auto rotation = polyStar->rotation->getValueAt(frame); + auto innerRadius = polyStar->innerRadius->getValueAt(frame); + auto outerRadius = polyStar->outerRadius->getValueAt(frame); + auto innerRoundness = polyStar->innerRoundness->getValueAt(frame); + auto outerRoundness = polyStar->outerRoundness->getValueAt(frame); + if (polyStar->polyType == PolyStarType::Star) { + ConvertPolyStartToPath(path, position.x, position.y, points, rotation, innerRadius, outerRadius, + innerRoundness, outerRoundness, polyStar->reversed); + } else { + ConvertPolygonToPath(path, position.x, position.y, points, rotation, outerRadius, + outerRoundness, polyStar->reversed); + } } void ShapePathToPath(ShapePathElement* shapePath, Path* path, Frame frame) { - auto pathData = shapePath->shapePath->getValueAt(frame); - if (pathData == nullptr) { - return; - } - path->addPath(ToPath(*pathData)); + auto pathData = shapePath->shapePath->getValueAt(frame); + if (pathData == nullptr) { + return; + } + path->addPath(ToPath(*pathData)); } PathFillType ToPathFillType(Enum rule) { - return rule == FillRule::EvenOdd ? PathFillType::EvenOdd : PathFillType::Winding; + return rule == FillRule::EvenOdd ? PathFillType::EvenOdd : PathFillType::Winding; } PaintElement* FillToPaint(FillElement* fill, Frame frame) { - if (fill->opacity->getValueAt(frame) <= 0) { - return nullptr; - } - auto paint = new PaintElement(PaintType::Fill); - paint->blendMode = fill->blendMode; - paint->opacity = fill->opacity->getValueAt(frame); - paint->color = fill->color->getValueAt(frame); - paint->pathFillType = ToPathFillType(fill->fillRule); - paint->compositeOrder = fill->composite; - return paint; + if (fill->opacity->getValueAt(frame) <= 0) { + return nullptr; + } + auto paint = new PaintElement(PaintType::Fill); + paint->blendMode = fill->blendMode; + paint->opacity = fill->opacity->getValueAt(frame); + paint->color = fill->color->getValueAt(frame); + paint->pathFillType = ToPathFillType(fill->fillRule); + paint->compositeOrder = fill->composite; + return paint; } PaintElement* StrokeToPaint(StrokeElement* stroke, Frame frame) { - if (stroke->opacity->getValueAt(frame) <= 0 || stroke->strokeWidth->getValueAt(frame) <= 0) { - return nullptr; - } - auto paint = new PaintElement(PaintType::Stroke); - paint->blendMode = stroke->blendMode; - paint->opacity = stroke->opacity->getValueAt(frame); - paint->compositeOrder = stroke->composite; - paint->color = stroke->color->getValueAt(frame); - paint->stroke.strokeWidth = stroke->strokeWidth->getValueAt(frame); - paint->stroke.lineCap = stroke->lineCap; - paint->stroke.lineJoin = stroke->lineJoin; - paint->stroke.miterLimit = stroke->miterLimit->getValueAt(frame); - if (!stroke->dashes.empty()) { - for (auto& dash : stroke->dashes) { - paint->stroke.dashes.push_back(dash->getValueAt(frame)); - } - paint->stroke.dashOffset = stroke->dashOffset->getValueAt(frame); - } - return paint; + if (stroke->opacity->getValueAt(frame) <= 0 || stroke->strokeWidth->getValueAt(frame) <= 0) { + return nullptr; + } + auto paint = new PaintElement(PaintType::Stroke); + paint->blendMode = stroke->blendMode; + paint->opacity = stroke->opacity->getValueAt(frame); + paint->compositeOrder = stroke->composite; + paint->color = stroke->color->getValueAt(frame); + paint->stroke.strokeWidth = stroke->strokeWidth->getValueAt(frame); + paint->stroke.lineCap = stroke->lineCap; + paint->stroke.lineJoin = stroke->lineJoin; + paint->stroke.miterLimit = stroke->miterLimit->getValueAt(frame); + if (!stroke->dashes.empty()) { + for (auto& dash : stroke->dashes) { + paint->stroke.dashes.push_back(dash->getValueAt(frame)); + } + paint->stroke.dashOffset = stroke->dashOffset->getValueAt(frame); + } + return paint; } void ConvertColorStop(const GradientColorHandle& gradientColor, std::vector& colorValues, std::vector& colorPositions) { - auto colorStops = gradientColor->colorStops; - for (size_t i = 0; i < colorStops.size(); i++) { - const auto& stop = colorStops[i]; - colorValues.push_back(stop.color); - colorPositions.push_back(stop.position); - if (stop.midpoint != 0.5f && i < colorStops.size() - 1) { - const auto& nextStop = colorStops[i + 1]; - auto midColor = Interpolate(stop.color, nextStop.color, 0.5f); - colorValues.push_back(midColor); - auto position = stop.position + (nextStop.position - stop.position) * stop.midpoint; - colorPositions.push_back(position); + auto colorStops = gradientColor->colorStops; + for (size_t i = 0; i < colorStops.size(); i++) { + const auto& stop = colorStops[i]; + colorValues.push_back(stop.color); + colorPositions.push_back(stop.position); + if (stop.midpoint != 0.5f && i < colorStops.size() - 1) { + const auto& nextStop = colorStops[i + 1]; + auto midColor = Interpolate(stop.color, nextStop.color, 0.5f); + colorValues.push_back(midColor); + auto position = stop.position + (nextStop.position - stop.position) * stop.midpoint; + colorPositions.push_back(position); + } } - } } void ConvertAlphaStop(const GradientColorHandle& gradientColor, std::vector& alphaValues, std::vector& alphaPositions) { - auto alphaStops = gradientColor->alphaStops; - for (size_t i = 0; i < alphaStops.size(); i++) { - const auto& stop = alphaStops[i]; - alphaValues.push_back(stop.opacity); - alphaPositions.push_back(stop.position); - if (stop.midpoint != 0.5f && i < alphaStops.size() - 1) { - const auto& nextStop = alphaStops[i + 1]; - auto midAlpha = Interpolate(stop.opacity, nextStop.opacity, 0.5f); - alphaValues.push_back(midAlpha); - auto position = stop.position + (nextStop.position - stop.position) * stop.midpoint; - alphaPositions.push_back(position); + auto alphaStops = gradientColor->alphaStops; + for (size_t i = 0; i < alphaStops.size(); i++) { + const auto& stop = alphaStops[i]; + alphaValues.push_back(stop.opacity); + alphaPositions.push_back(stop.position); + if (stop.midpoint != 0.5f && i < alphaStops.size() - 1) { + const auto& nextStop = alphaStops[i + 1]; + auto midAlpha = Interpolate(stop.opacity, nextStop.opacity, 0.5f); + alphaValues.push_back(midAlpha); + auto position = stop.position + (nextStop.position - stop.position) * stop.midpoint; + alphaPositions.push_back(position); + } } - } } GradientPaint MakeGradientPaint(Enum fillType, Point startPoint, Point endPoint, const GradientColorHandle& gradientColor, const Matrix& matrix) { - Point points[2] = {Point::Make(startPoint.x, startPoint.y), Point::Make(endPoint.x, endPoint.y)}; - matrix.mapPoints(points, 2); - GradientPaint gradient = {}; - gradient.gradientType = fillType; - gradient.startPoint = points[0]; - gradient.endPoint = points[1]; - - std::vector colorValues; - std::vector colorPositions; - ConvertColorStop(gradientColor, colorValues, colorPositions); - - std::vector alphaValues; - std::vector alphaPositions; - ConvertAlphaStop(gradientColor, alphaValues, alphaPositions); - - size_t colorIndex = 0; - size_t alphaIndex = 0; - while (colorIndex < colorValues.size() && alphaIndex < alphaValues.size()) { - auto colorPosition = colorPositions[colorIndex]; - auto alphaPosition = alphaPositions[alphaIndex]; - if (colorPosition == alphaPosition) { - gradient.positions.push_back(colorPosition); - gradient.colors.push_back(colorValues[colorIndex++]); - gradient.alphas.push_back(alphaValues[alphaIndex++]); - } else if (colorPosition < alphaPosition) { - gradient.positions.push_back(colorPosition); - Opacity alpha; - if (alphaIndex > 0) { - auto lastPosition = alphaPositions[alphaIndex - 1]; - auto factor = (colorPosition - lastPosition) * 1.0f / (alphaPosition - lastPosition); - alpha = Interpolate(alphaValues[alphaIndex - 1], alphaValues[alphaIndex], factor); - } else { - alpha = alphaValues[alphaIndex]; - } - gradient.colors.push_back(colorValues[colorIndex++]); - gradient.alphas.push_back(alpha); - } else { - gradient.positions.push_back(alphaPosition); - Color color = {}; - if (colorIndex > 0) { - auto lastPosition = colorPositions[colorIndex - 1]; - auto factor = (alphaPosition - lastPosition) * 1.0f / (colorPosition - lastPosition); - auto lastColor = colorValues[colorIndex - 1]; - auto currentColor = colorValues[colorIndex]; - color = Interpolate(lastColor, currentColor, factor); - } else { - color = colorValues[colorIndex]; - } - gradient.colors.push_back(color); - gradient.alphas.push_back(alphaValues[alphaIndex++]); - } - } - - auto lastAlpha = alphaValues.back(); - while (colorIndex < colorValues.size()) { - gradient.positions.push_back(colorPositions[colorIndex]); - gradient.colors.push_back(colorValues[colorIndex++]); - gradient.alphas.push_back(lastAlpha); - } - - auto lastColor = colorValues.back(); - while (alphaIndex < alphaValues.size()) { - gradient.positions.push_back(alphaPositions[alphaIndex]); - gradient.colors.push_back(lastColor); - gradient.alphas.push_back(alphaValues[alphaIndex++]); - } - return gradient; + Point points[2] = {Point::Make(startPoint.x, startPoint.y), Point::Make(endPoint.x, endPoint.y)}; + matrix.mapPoints(points, 2); + GradientPaint gradient = {}; + gradient.gradientType = fillType; + gradient.startPoint = points[0]; + gradient.endPoint = points[1]; + + std::vector colorValues; + std::vector colorPositions; + ConvertColorStop(gradientColor, colorValues, colorPositions); + + std::vector alphaValues; + std::vector alphaPositions; + ConvertAlphaStop(gradientColor, alphaValues, alphaPositions); + + size_t colorIndex = 0; + size_t alphaIndex = 0; + while (colorIndex < colorValues.size() && alphaIndex < alphaValues.size()) { + auto colorPosition = colorPositions[colorIndex]; + auto alphaPosition = alphaPositions[alphaIndex]; + if (colorPosition == alphaPosition) { + gradient.positions.push_back(colorPosition); + gradient.colors.push_back(colorValues[colorIndex++]); + gradient.alphas.push_back(alphaValues[alphaIndex++]); + } else if (colorPosition < alphaPosition) { + gradient.positions.push_back(colorPosition); + Opacity alpha; + if (alphaIndex > 0) { + auto lastPosition = alphaPositions[alphaIndex - 1]; + auto factor = (colorPosition - lastPosition) * 1.0f / (alphaPosition - lastPosition); + alpha = Interpolate(alphaValues[alphaIndex - 1], alphaValues[alphaIndex], factor); + } else { + alpha = alphaValues[alphaIndex]; + } + gradient.colors.push_back(colorValues[colorIndex++]); + gradient.alphas.push_back(alpha); + } else { + gradient.positions.push_back(alphaPosition); + Color color = {}; + if (colorIndex > 0) { + auto lastPosition = colorPositions[colorIndex - 1]; + auto factor = (alphaPosition - lastPosition) * 1.0f / (colorPosition - lastPosition); + auto lastColor = colorValues[colorIndex - 1]; + auto currentColor = colorValues[colorIndex]; + color = Interpolate(lastColor, currentColor, factor); + } else { + color = colorValues[colorIndex]; + } + gradient.colors.push_back(color); + gradient.alphas.push_back(alphaValues[alphaIndex++]); + } + } + + auto lastAlpha = alphaValues.back(); + while (colorIndex < colorValues.size()) { + gradient.positions.push_back(colorPositions[colorIndex]); + gradient.colors.push_back(colorValues[colorIndex++]); + gradient.alphas.push_back(lastAlpha); + } + + auto lastColor = colorValues.back(); + while (alphaIndex < alphaValues.size()) { + gradient.positions.push_back(alphaPositions[alphaIndex]); + gradient.colors.push_back(lastColor); + gradient.alphas.push_back(alphaValues[alphaIndex++]); + } + return gradient; } PaintElement* GradientFillToPaint(GradientFillElement* fill, const Matrix& matrix, Frame frame) { - if (fill->opacity->getValueAt(frame) <= 0) { - return nullptr; - } - auto paint = new PaintElement(PaintType::GradientFill); - paint->blendMode = fill->blendMode; - paint->opacity = fill->opacity->getValueAt(frame); - paint->compositeOrder = fill->composite; - paint->gradient = - MakeGradientPaint(fill->fillType, fill->startPoint->getValueAt(frame), - fill->endPoint->getValueAt(frame), fill->colors->getValueAt(frame), matrix); - paint->pathFillType = ToPathFillType(fill->fillRule); + if (fill->opacity->getValueAt(frame) <= 0) { + return nullptr; + } + auto paint = new PaintElement(PaintType::GradientFill); + paint->blendMode = fill->blendMode; + paint->opacity = fill->opacity->getValueAt(frame); + paint->compositeOrder = fill->composite; + paint->gradient = + MakeGradientPaint(fill->fillType, fill->startPoint->getValueAt(frame), + fill->endPoint->getValueAt(frame), fill->colors->getValueAt(frame), matrix); + paint->pathFillType = ToPathFillType(fill->fillRule); - return paint; + return paint; } PaintElement* GradientStrokeToPaint(GradientStrokeElement* stroke, const Matrix& matrix, Frame frame) { - if (stroke->opacity->getValueAt(frame) <= 0 || stroke->strokeWidth->getValueAt(frame) <= 0) { - return nullptr; - } - auto paint = new PaintElement(PaintType::GradientStroke); - paint->blendMode = stroke->blendMode; - paint->opacity = stroke->opacity->getValueAt(frame); - paint->compositeOrder = stroke->composite; - paint->stroke.strokeWidth = stroke->strokeWidth->getValueAt(frame); - paint->stroke.lineCap = stroke->lineCap; - paint->stroke.lineJoin = stroke->lineJoin; - paint->stroke.miterLimit = stroke->miterLimit->getValueAt(frame); - if (!stroke->dashes.empty()) { - for (auto& dash : stroke->dashes) { - paint->stroke.dashes.push_back(dash->getValueAt(frame)); - } - paint->stroke.dashOffset = stroke->dashOffset->getValueAt(frame); - } - paint->gradient = MakeGradientPaint(stroke->fillType, stroke->startPoint->getValueAt(frame), - stroke->endPoint->getValueAt(frame), - stroke->colors->getValueAt(frame), matrix); - return paint; + if (stroke->opacity->getValueAt(frame) <= 0 || stroke->strokeWidth->getValueAt(frame) <= 0) { + return nullptr; + } + auto paint = new PaintElement(PaintType::GradientStroke); + paint->blendMode = stroke->blendMode; + paint->opacity = stroke->opacity->getValueAt(frame); + paint->compositeOrder = stroke->composite; + paint->stroke.strokeWidth = stroke->strokeWidth->getValueAt(frame); + paint->stroke.lineCap = stroke->lineCap; + paint->stroke.lineJoin = stroke->lineJoin; + paint->stroke.miterLimit = stroke->miterLimit->getValueAt(frame); + if (!stroke->dashes.empty()) { + for (auto& dash : stroke->dashes) { + paint->stroke.dashes.push_back(dash->getValueAt(frame)); + } + paint->stroke.dashOffset = stroke->dashOffset->getValueAt(frame); + } + paint->gradient = MakeGradientPaint(stroke->fillType, stroke->startPoint->getValueAt(frame), + stroke->endPoint->getValueAt(frame), + stroke->colors->getValueAt(frame), matrix); + return paint; } struct TrimSegment { - float start; - float end; + float start; + float end; }; void ApplyTrimPathIndividually(const std::vector& pathList, std::vector segments) { - float totalLength = 0; - std::vector> measureList; - for (auto& path : pathList) { - auto pathMeasure = PathMeasure::MakeFrom(*path); - totalLength += pathMeasure->getLength(); - measureList.push_back(std::move(pathMeasure)); - } - for (auto& segment : segments) { - segment.start *= totalLength; - segment.end *= totalLength; - } - float addedLength = 0; - int index = 0; - Path tempPath = {}; - for (auto& pathMeasure : measureList) { - auto& path = pathList[index++]; - auto pathLength = pathMeasure->getLength(); - if (pathLength == 0) { - continue; - } - bool intersect = false; + float totalLength = 0; + std::vector> measureList; + for (auto& path : pathList) { + auto pathMeasure = PathMeasure::MakeFrom(*path); + totalLength += pathMeasure->getLength(); + measureList.push_back(std::move(pathMeasure)); + } for (auto& segment : segments) { - if (addedLength >= segment.end || addedLength + pathLength <= segment.start) { - continue; - } - intersect = true; - pathMeasure->getSegment(segment.start - addedLength, segment.end - addedLength, &tempPath); - } - if (intersect) { - *path = tempPath; - } else { - path->reset(); + segment.start *= totalLength; + segment.end *= totalLength; + } + float addedLength = 0; + int index = 0; + Path tempPath = {}; + for (auto& pathMeasure : measureList) { + auto& path = pathList[index++]; + auto pathLength = pathMeasure->getLength(); + if (pathLength == 0) { + continue; + } + bool intersect = false; + for (auto& segment : segments) { + if (addedLength >= segment.end || addedLength + pathLength <= segment.start) { + continue; + } + intersect = true; + pathMeasure->getSegment(segment.start - addedLength, segment.end - addedLength, &tempPath); + } + if (intersect) { + *path = tempPath; + } else { + path->reset(); + } + tempPath.reset(); + addedLength += pathLength; } - tempPath.reset(); - addedLength += pathLength; - } } void ApplyTrimPaths(TrimPathsElement* trimPaths, std::vector& pathList, float start, float end, bool reversed) { - if (start == 0 && end == 1) { - return; - } - std::vector segments; - if (start < 0) { - // [start...0...end...1] - segments.push_back({start + 1, 1}); - segments.push_back({0, end}); - } else if (end > 1) { - // [0...start...1...end] - segments.push_back({start, 1}); - segments.push_back({0, end - 1}); - } else { - // [0...start...end...1] - segments.push_back({start, end}); - } - if (trimPaths->trimType == TrimPathsType::Simultaneously) { - Path tempPath = {}; - for (auto& path : pathList) { - auto pathMeasure = PathMeasure::MakeFrom(*path); - auto length = pathMeasure->getLength(); - if (length == 0) { - continue; - } - for (auto segment : segments) { - auto startD = length * segment.start; - auto endD = length * segment.end; - pathMeasure->getSegment(startD, endD, &tempPath); - } - *path = tempPath; - tempPath.reset(); - } - } else { - auto list = pathList; - if (reversed) { - std::reverse(list.begin(), list.end()); + if (start == 0 && end == 1) { + return; + } + std::vector segments; + if (start < 0) { + // [start...0...end...1] + segments.push_back({start + 1, 1}); + segments.push_back({0, end}); + } else if (end > 1) { + // [0...start...1...end] + segments.push_back({start, 1}); + segments.push_back({0, end - 1}); + } else { + // [0...start...end...1] + segments.push_back({start, end}); + } + if (trimPaths->trimType == TrimPathsType::Simultaneously) { + Path tempPath = {}; + for (auto& path : pathList) { + auto pathMeasure = PathMeasure::MakeFrom(*path); + auto length = pathMeasure->getLength(); + if (length == 0) { + continue; + } + for (auto segment : segments) { + auto startD = length * segment.start; + auto endD = length * segment.end; + pathMeasure->getSegment(startD, endD, &tempPath); + } + *path = tempPath; + tempPath.reset(); + } + } else { + auto list = pathList; + if (reversed) { + std::reverse(list.begin(), list.end()); + } + ApplyTrimPathIndividually(list, segments); } - ApplyTrimPathIndividually(list, segments); - } } void ApplyTrimPaths(TrimPathsElement* trimPaths, std::vector pathList, Frame frame) { - auto start = trimPaths->start->getValueAt(frame); - auto end = trimPaths->end->getValueAt(frame); - auto offset = fmodf(trimPaths->offset->getValueAt(frame), 360.0f) / 360.0f; - start += offset; - end += offset; - if (fabsf(start - end) < FLT_EPSILON) { - for (auto& path : pathList) { - path->reset(); - } - return; - } - bool reversed = start > end; - if (reversed) { - start = 1 - start; - end = 1 - end; - for (auto& path : pathList) { - path->reverse(); + auto start = trimPaths->start->getValueAt(frame); + auto end = trimPaths->end->getValueAt(frame); + auto offset = fmodf(trimPaths->offset->getValueAt(frame), 360.0f) / 360.0f; + start += offset; + end += offset; + if (fabsf(start - end) < FLT_EPSILON) { + for (auto& path : pathList) { + path->reset(); + } + return; + } + bool reversed = start > end; + if (reversed) { + start = 1 - start; + end = 1 - end; + for (auto& path : pathList) { + path->reverse(); + } } - } - if (start > 1 && end > 1) { - start -= 1.0f; - end -= 1.0f; - } else if (start < 0 && end < 0) { - start += 1.0f; - end += 1.0f; - } - ApplyTrimPaths(trimPaths, pathList, start, end, reversed); + if (start > 1 && end > 1) { + start -= 1.0f; + end -= 1.0f; + } else if (start < 0 && end < 0) { + start += 1.0f; + end += 1.0f; + } + ApplyTrimPaths(trimPaths, pathList, start, end, reversed); } void ApplyMergePaths(MergePathsElement* mergePaths, GroupElement* group) { - auto pathList = group->pathList(); - if (pathList.empty()) { - return; - } - PathOp pathOp; - switch (mergePaths->mode) { + auto pathList = group->pathList(); + if (pathList.empty()) { + return; + } + PathOp pathOp; + switch (mergePaths->mode) { case MergePathsMode::Merge: - pathOp = PathOp::Append; - break; + pathOp = PathOp::Append; + break; case MergePathsMode::Intersect: - pathOp = PathOp::Intersect; - break; + pathOp = PathOp::Intersect; + break; case MergePathsMode::Subtract: - pathOp = PathOp::Difference; - break; + pathOp = PathOp::Difference; + break; case MergePathsMode::ExcludeIntersections: - pathOp = PathOp::XOR; - break; + pathOp = PathOp::XOR; + break; default: - pathOp = PathOp::Union; - break; - } - auto tempPath = *(pathList[0]); - auto size = static_cast(pathList.size()); - for (int i = 1; i < size; i++) { - auto path = pathList[i]; - tempPath.addPath(*path, pathOp); - } - group->clear(); - auto pathElement = new PathElement(); - pathElement->path = tempPath; - group->elements.push_back(pathElement); + pathOp = PathOp::Union; + break; + } + auto tempPath = *(pathList[0]); + auto size = static_cast(pathList.size()); + for (int i = 1; i < size; i++) { + auto path = pathList[i]; + tempPath.addPath(*path, pathOp); + } + group->clear(); + auto pathElement = new PathElement(); + pathElement->path = tempPath; + group->elements.push_back(pathElement); } void ApplyRepeater(RepeaterElement* repeater, GroupElement* group, Frame frame) { - auto copies = repeater->copies->getValueAt(frame); - if (copies < 0) { - return; - } - if (copies == 0) { - group->clear(); - return; - } - auto maxCount = ceilf(copies); - auto offset = repeater->offset->getValueAt(frame); - auto anchorPoint = repeater->transform->anchorPoint->getValueAt(frame); - auto position = repeater->transform->position->getValueAt(frame); - auto scale = repeater->transform->scale->getValueAt(frame); - auto rotation = repeater->transform->rotation->getValueAt(frame); - auto startOpacity = repeater->transform->startOpacity->getValueAt(frame); - auto endOpacity = repeater->transform->endOpacity->getValueAt(frame); - float i = 0; - std::vector elements = {}; - while (i < maxCount) { - auto progress = i + offset; - auto newGroup = static_cast(group->clone().release()); - if (repeater->composite == RepeaterOrder::Below) { - elements.push_back(newGroup); - } else { - elements.insert(elements.begin(), newGroup); + auto copies = repeater->copies->getValueAt(frame); + if (copies < 0) { + return; } - if (i == maxCount - 1) { - if (progress != copies + offset) { - newGroup->opacity = static_cast(newGroup->opacity * (copies - i)); - } + if (copies == 0) { + group->clear(); + return; } - auto matrix = Matrix::I(); - matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); - matrix.postScale(powf(scale.x, progress), powf(scale.y, progress)); - matrix.postRotate(rotation * progress); - matrix.postTranslate(position.x * progress, position.y * progress); - matrix.postTranslate(anchorPoint.x, anchorPoint.y); - newGroup->applyMatrix(matrix); - auto newOpacity = Interpolate(startOpacity, endOpacity, progress / maxCount); - newGroup->opacity = OpacityConcat(newGroup->opacity, newOpacity); - i += 1.0f; - } - group->clear(); - group->elements = elements; + auto maxCount = ceilf(copies); + auto offset = repeater->offset->getValueAt(frame); + auto anchorPoint = repeater->transform->anchorPoint->getValueAt(frame); + auto position = repeater->transform->position->getValueAt(frame); + auto scale = repeater->transform->scale->getValueAt(frame); + auto rotation = repeater->transform->rotation->getValueAt(frame); + auto startOpacity = repeater->transform->startOpacity->getValueAt(frame); + auto endOpacity = repeater->transform->endOpacity->getValueAt(frame); + float i = 0; + std::vector elements = {}; + while (i < maxCount) { + auto progress = i + offset; + auto newGroup = static_cast(group->clone().release()); + if (repeater->composite == RepeaterOrder::Below) { + elements.push_back(newGroup); + } else { + elements.insert(elements.begin(), newGroup); + } + if (i == maxCount - 1) { + if (progress != copies + offset) { + newGroup->opacity = static_cast(newGroup->opacity * (copies - i)); + } + } + auto matrix = Matrix::I(); + matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); + matrix.postScale(powf(scale.x, progress), powf(scale.y, progress)); + matrix.postRotate(rotation * progress); + matrix.postTranslate(position.x * progress, position.y * progress); + matrix.postTranslate(anchorPoint.x, anchorPoint.y); + newGroup->applyMatrix(matrix); + auto newOpacity = Interpolate(startOpacity, endOpacity, progress / maxCount); + newGroup->opacity = OpacityConcat(newGroup->opacity, newOpacity); + i += 1.0f; + } + group->clear(); + group->elements = elements; } void ApplyRoundCorners(RoundCornersElement* roundCorners, std::vector pathList, Frame frame) { - auto radius = roundCorners->radius->getValueAt(frame); - auto effect = PathEffect::MakeCorner(radius); - if (effect == nullptr) { - return; - } - for (auto& path : pathList) { - effect->applyTo(path); - } + auto radius = roundCorners->radius->getValueAt(frame); + auto effect = PathEffect::MakeCorner(radius); + if (effect == nullptr) { + return; + } + for (auto& path : pathList) { + effect->applyTo(path); + } } void SkewFromAxis(Matrix* matrix, float skew, float skewAxis) { - if (skew == 0 && skewAxis == 0) { - return; - } - auto u = cosf(skewAxis); - auto v = sinf(skewAxis); - Matrix temp = {}; - temp.setAll(u, -v, 0, v, u, 0, 0, 0, 1); - matrix->postConcat(temp); - auto w = tanf(skew); - temp.setAll(1, w, 0, 0, 1, 0, 0, 0, 1); - matrix->postConcat(temp); - temp.setAll(u, v, 0, -v, u, 0, 0, 0, 1); - matrix->postConcat(temp); + if (skew == 0 && skewAxis == 0) { + return; + } + auto u = cosf(skewAxis); + auto v = sinf(skewAxis); + Matrix temp = {}; + temp.setAll(u, -v, 0, v, u, 0, 0, 0, 1); + matrix->postConcat(temp); + auto w = tanf(skew); + temp.setAll(1, w, 0, 0, 1, 0, 0, 0, 1); + matrix->postConcat(temp); + temp.setAll(u, v, 0, -v, u, 0, 0, 0, 1); + matrix->postConcat(temp); } Transform ShapeTransformToTransform(const ShapeTransform* transform, Frame frame) { - auto matrix = Matrix::I(); - auto anchorPoint = transform->anchorPoint->getValueAt(frame); - auto scale = transform->scale->getValueAt(frame); - auto position = transform->position->getValueAt(frame); - auto skew = transform->skew->getValueAt(frame); - auto skewAxis = transform->skewAxis->getValueAt(frame); - auto rotation = transform->rotation->getValueAt(frame); - auto opacity = transform->opacity->getValueAt(frame); - matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); - matrix.postScale(scale.x, scale.y); - if (skew != 0) { - SkewFromAxis(&matrix, DegreesToRadians(-skew), DegreesToRadians(skewAxis)); - } - matrix.postRotate(rotation); - matrix.postTranslate(position.x, position.y); - return {matrix, opacity}; + auto matrix = Matrix::I(); + auto anchorPoint = transform->anchorPoint->getValueAt(frame); + auto scale = transform->scale->getValueAt(frame); + auto position = transform->position->getValueAt(frame); + auto skew = transform->skew->getValueAt(frame); + auto skewAxis = transform->skewAxis->getValueAt(frame); + auto rotation = transform->rotation->getValueAt(frame); + auto opacity = transform->opacity->getValueAt(frame); + matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); + matrix.postScale(scale.x, scale.y); + if (skew != 0) { + SkewFromAxis(&matrix, DegreesToRadians(-skew), DegreesToRadians(skewAxis)); + } + matrix.postRotate(rotation); + matrix.postTranslate(position.x, position.y); + return {matrix, opacity}; } void RenderElements(const std::vector& list, const Matrix& parentMatrix, @@ -754,224 +756,228 @@ void RenderElements(const std::vector& list, const Matrix& parent void RenderElements_ShapeGroup(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto shape = reinterpret_cast(element); - auto transform = ShapeTransformToTransform(shape->transform, frame); - transform.matrix.postConcat(parentMatrix); - auto group = new GroupElement(); - group->opacity = transform.opacity; - group->blendMode = shape->blendMode; - RenderElements(shape->elements, transform.matrix, group, frame); - parentGroup->elements.push_back(group); + auto shape = reinterpret_cast(element); + auto transform = ShapeTransformToTransform(shape->transform, frame); + transform.matrix.postConcat(parentMatrix); + auto group = new GroupElement(); + group->opacity = transform.opacity; + group->blendMode = shape->blendMode; + RenderElements(shape->elements, transform.matrix, group, frame); + parentGroup->elements.push_back(group); } void RenderElements_Rectangle(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto pathElement = new PathElement(); - RectangleToPath(static_cast(element), &pathElement->path, frame); - pathElement->path.transform(parentMatrix); - parentGroup->elements.push_back(pathElement); + auto pathElement = new PathElement(); + RectangleToPath(static_cast(element), &pathElement->path, frame); + pathElement->path.transform(parentMatrix); + parentGroup->elements.push_back(pathElement); } void RenderElements_Ellipse(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto pathElement = new PathElement(); - EllipseToPath(static_cast(element), &pathElement->path, frame); - pathElement->path.transform(parentMatrix); - parentGroup->elements.push_back(pathElement); + auto pathElement = new PathElement(); + EllipseToPath(static_cast(element), &pathElement->path, frame); + pathElement->path.transform(parentMatrix); + parentGroup->elements.push_back(pathElement); } void RenderElements_PolyStar(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto pathElement = new PathElement(); - PolyStarToPath(static_cast(element), &pathElement->path, frame); - pathElement->path.transform(parentMatrix); - parentGroup->elements.push_back(pathElement); + auto pathElement = new PathElement(); + PolyStarToPath(static_cast(element), &pathElement->path, frame); + pathElement->path.transform(parentMatrix); + parentGroup->elements.push_back(pathElement); } void RenderElements_ShapePath(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto pathElement = new PathElement(); - ShapePathToPath(static_cast(element), &pathElement->path, frame); - pathElement->path.transform(parentMatrix); - parentGroup->elements.push_back(pathElement); + auto pathElement = new PathElement(); + ShapePathToPath(static_cast(element), &pathElement->path, frame); + pathElement->path.transform(parentMatrix); + parentGroup->elements.push_back(pathElement); } void RenderElements_Fill(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame frame) { - auto fill = static_cast(element); - auto paint = FillToPaint(fill, frame); - if (paint != nullptr) { - parentGroup->elements.push_back(paint); - } + auto fill = static_cast(element); + auto paint = FillToPaint(fill, frame); + if (paint != nullptr) { + parentGroup->elements.push_back(paint); + } } void RenderElements_Stroke(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame frame) { - auto stroke = static_cast(element); - auto paint = StrokeToPaint(stroke, frame); - if (paint != nullptr) { - parentGroup->elements.push_back(paint); - } + auto stroke = static_cast(element); + auto paint = StrokeToPaint(stroke, frame); + if (paint != nullptr) { + parentGroup->elements.push_back(paint); + } } void RenderElements_GradientFill(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto fill = static_cast(element); - auto paint = GradientFillToPaint(fill, parentMatrix, frame); - if (paint != nullptr) { - parentGroup->elements.push_back(paint); - } + auto fill = static_cast(element); + auto paint = GradientFillToPaint(fill, parentMatrix, frame); + if (paint != nullptr) { + parentGroup->elements.push_back(paint); + } } void RenderElements_GradientStroke(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - auto stroke = static_cast(element); - auto paint = GradientStrokeToPaint(stroke, parentMatrix, frame); - if (paint != nullptr) { - parentGroup->elements.push_back(paint); - } + auto stroke = static_cast(element); + auto paint = GradientStrokeToPaint(stroke, parentMatrix, frame); + if (paint != nullptr) { + parentGroup->elements.push_back(paint); + } } void RenderElements_MergePaths(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame) { - ApplyMergePaths(static_cast(element), parentGroup); + ApplyMergePaths(static_cast(element), parentGroup); } void RenderElements_Repeater(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame frame) { - ApplyRepeater(static_cast(element), parentGroup, frame); + ApplyRepeater(static_cast(element), parentGroup, frame); } void RenderElements_TrimPaths(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame frame) { - ApplyTrimPaths(static_cast(element), parentGroup->pathList(), frame); + ApplyTrimPaths(static_cast(element), parentGroup->pathList(), frame); } void RenderElements_RoundCorners(ShapeElement* element, const Matrix&, GroupElement* parentGroup, Frame frame) { - ApplyRoundCorners(static_cast(element), parentGroup->pathList(), frame); + ApplyRoundCorners(static_cast(element), parentGroup->pathList(), frame); } using RenderElementsHandler = void(ShapeElement* element, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame); static const std::unordered_map, EnumClassHash> - elementHandlers = {{ShapeType::ShapeGroup, RenderElements_ShapeGroup}, - {ShapeType::Rectangle, RenderElements_Rectangle}, - {ShapeType::Ellipse, RenderElements_Ellipse}, - {ShapeType::PolyStar, RenderElements_PolyStar}, - {ShapeType::ShapePath, RenderElements_ShapePath}, - {ShapeType::Fill, RenderElements_Fill}, - {ShapeType::Stroke, RenderElements_Stroke}, - {ShapeType::GradientFill, RenderElements_GradientFill}, - {ShapeType::GradientStroke, RenderElements_GradientStroke}, - {ShapeType::MergePaths, RenderElements_MergePaths}, - {ShapeType::Repeater, RenderElements_Repeater}, - {ShapeType::TrimPaths, RenderElements_TrimPaths}, - {ShapeType::RoundCorners, RenderElements_RoundCorners}}; +elementHandlers = {{ShapeType::ShapeGroup, RenderElements_ShapeGroup}, + {ShapeType::Rectangle, RenderElements_Rectangle}, + {ShapeType::Ellipse, RenderElements_Ellipse}, + {ShapeType::PolyStar, RenderElements_PolyStar}, + {ShapeType::ShapePath, RenderElements_ShapePath}, + {ShapeType::Fill, RenderElements_Fill}, + {ShapeType::Stroke, RenderElements_Stroke}, + {ShapeType::GradientFill, RenderElements_GradientFill}, + {ShapeType::GradientStroke, RenderElements_GradientStroke}, + {ShapeType::MergePaths, RenderElements_MergePaths}, + {ShapeType::Repeater, RenderElements_Repeater}, + {ShapeType::TrimPaths, RenderElements_TrimPaths}, + {ShapeType::RoundCorners, RenderElements_RoundCorners} +}; void RenderElements(const std::vector& list, const Matrix& parentMatrix, GroupElement* parentGroup, Frame frame) { - for (auto& element : list) { - auto iter = elementHandlers.find(element->type()); - if (iter != elementHandlers.end()) { - iter->second(element, parentMatrix, parentGroup, frame); + for (auto& element : list) { + auto iter = elementHandlers.find(element->type()); + if (iter != elementHandlers.end()) { + iter->second(element, parentMatrix, parentGroup, frame); + } } - } } std::unique_ptr CreateDashEffect(const std::vector& dashes, float dashOffset) { - auto dashCount = dashes.size(); - auto size = static_cast(dashCount); - int times = 1; - if (size % 2 == 1) { - size *= 2; - times = 2; - } - auto dashList = new float[size]; - int index = 0; - for (int i = 0; i < times; i++) { - for (size_t j = 0; j < dashCount; j++) { - dashList[index++] = static_cast(dashes[j]); - } - } - auto dashEffect = PathEffect::MakeDash(dashList, size, dashOffset); - delete[] dashList; - return dashEffect; + auto dashCount = dashes.size(); + auto size = static_cast(dashCount); + int times = 1; + if (size % 2 == 1) { + size *= 2; + times = 2; + } + auto dashList = new float[size]; + int index = 0; + for (int i = 0; i < times; i++) { + for (size_t j = 0; j < dashCount; j++) { + dashList[index++] = static_cast(dashes[j]); + } + } + auto dashEffect = PathEffect::MakeDash(dashList, size, dashOffset); + delete[] dashList; + return dashEffect; } void ApplyStrokeToPath(Path* path, const StrokePaint& stroke) { - if (!stroke.dashes.empty()) { - auto dashEffect = CreateDashEffect(stroke.dashes, stroke.dashOffset); - if (dashEffect) { - dashEffect->applyTo(path); + if (!stroke.dashes.empty()) { + auto dashEffect = CreateDashEffect(stroke.dashes, stroke.dashOffset); + if (dashEffect) { + dashEffect->applyTo(path); + } + } + auto strokeEffect = PathEffect::MakeStroke(stroke.getStroke()); + if (strokeEffect) { + strokeEffect->applyTo(path); } - } - auto strokeEffect = PathEffect::MakeStroke(stroke.getStroke()); - if (strokeEffect) { - strokeEffect->applyTo(path); - } } std::shared_ptr RenderShape(PaintElement* paint, Path* path) { - Path shapePath = *path; - auto paintType = paint->paintType; - if (paintType == PaintType::Stroke || paintType == PaintType::GradientStroke) { - ApplyStrokeToPath(&shapePath, paint->stroke); - } - if (shapePath.getFillType() == PathFillType::Winding) { - shapePath.setFillType(paint->pathFillType); - } - std::shared_ptr shape = nullptr; - if (paintType == PaintType::GradientStroke || paintType == PaintType::GradientFill) { - shape = Shape::MakeFrom(shapePath, paint->gradient); - } else { - shape = Shape::MakeFrom(shapePath, paint->color); - } - auto modifier = Modifier::MakeBlend(paint->opacity, paint->blendMode); - return Graphic::MakeCompose(shape, modifier); + Path shapePath = *path; + auto paintType = paint->paintType; + if (paintType == PaintType::Stroke || paintType == PaintType::GradientStroke) { + ApplyStrokeToPath(&shapePath, paint->stroke); + } + if (shapePath.getFillType() == PathFillType::Winding) { + shapePath.setFillType(paint->pathFillType); + } + std::shared_ptr shape = nullptr; + if (paintType == PaintType::GradientStroke || paintType == PaintType::GradientFill) { + shape = Shape::MakeFrom(shapePath, paint->gradient); + } else { + shape = Shape::MakeFrom(shapePath, paint->color); + } + auto modifier = Modifier::MakeBlend(paint->opacity, paint->blendMode); + return Graphic::MakeCompose(shape, modifier); } std::shared_ptr RenderShape(GroupElement* group, Path* path) { - std::vector> contents = {}; - for (auto& element : group->elements) { - switch (element->type()) { - case ElementDataType::Path: { - auto pathElement = reinterpret_cast(element); - path->addPath(pathElement->path); - } break; - case ElementDataType::Paint: { - auto paint = reinterpret_cast(element); - auto shape = RenderShape(paint, path); - if (shape) { - if (paint->compositeOrder == CompositeOrder::AbovePreviousInSameGroup) { - contents.push_back(shape); - } else { - contents.insert(contents.begin(), shape); - } + std::vector> contents = {}; + for (auto& element : group->elements) { + switch (element->type()) { + case ElementDataType::Path: { + auto pathElement = reinterpret_cast(element); + path->addPath(pathElement->path); } - } break; - case ElementDataType::Group: { - Path tempPath = {}; - auto shape = RenderShape(static_cast(element), &tempPath); - path->addPath(tempPath); - if (shape) { - contents.insert(contents.begin(), shape); + break; + case ElementDataType::Paint: { + auto paint = reinterpret_cast(element); + auto shape = RenderShape(paint, path); + if (shape) { + if (paint->compositeOrder == CompositeOrder::AbovePreviousInSameGroup) { + contents.push_back(shape); + } else { + contents.insert(contents.begin(), shape); + } + } + } + break; + case ElementDataType::Group: { + Path tempPath = {}; + auto shape = RenderShape(static_cast(element), &tempPath); + path->addPath(tempPath); + if (shape) { + contents.insert(contents.begin(), shape); + } + } + break; } - } break; } - } - auto shape = Graphic::MakeCompose(contents); - auto modifier = Modifier::MakeBlend(group->opacity, group->blendMode); - return Graphic::MakeCompose(shape, modifier); + auto shape = Graphic::MakeCompose(contents); + auto modifier = Modifier::MakeBlend(group->opacity, group->blendMode); + return Graphic::MakeCompose(shape, modifier); } std::shared_ptr RenderShapes(const std::vector& contents, Frame layerFrame) { - GroupElement rootGroup; - auto matrix = Matrix::I(); - RenderElements(contents, matrix, &rootGroup, layerFrame); - Path tempPath = {}; - return RenderShape(&rootGroup, &tempPath); + GroupElement rootGroup; + auto matrix = Matrix::I(); + RenderElements(contents, matrix, &rootGroup, layerFrame); + Path tempPath = {}; + return RenderShape(&rootGroup, &tempPath); } } // namespace pag diff --git a/src/rendering/renderers/TextAnimatorRenderer.cpp b/src/rendering/renderers/TextAnimatorRenderer.cpp index cca6c8107b..ddad013693 100644 --- a/src/rendering/renderers/TextAnimatorRenderer.cpp +++ b/src/rendering/renderers/TextAnimatorRenderer.cpp @@ -22,227 +22,227 @@ namespace pag { // 判断是否包含动画 static bool HasAnimator(const std::vector* animators) { - if (animators != nullptr) { - for (auto animator : *animators) { - auto typographyProperties = animator->typographyProperties; - if (typographyProperties != nullptr) { - if (typographyProperties->trackingAmount != nullptr || - typographyProperties->position != nullptr || typographyProperties->scale != nullptr || - typographyProperties->rotation != nullptr || typographyProperties->opacity != nullptr) { - return true; + if (animators != nullptr) { + for (auto animator : *animators) { + auto typographyProperties = animator->typographyProperties; + if (typographyProperties != nullptr) { + if (typographyProperties->trackingAmount != nullptr || + typographyProperties->position != nullptr || typographyProperties->scale != nullptr || + typographyProperties->rotation != nullptr || typographyProperties->opacity != nullptr) { + return true; + } + } } - } } - } - return false; + return false; } // 根据对齐方式计算(字间距)偏移量 static float CalculateOffsetByJustification(Enum justification, float trackingAnimatorLen) { - float offset = 0.0f; - switch (justification) { + float offset = 0.0f; + switch (justification) { case ParagraphJustification::RightJustify: - offset = -trackingAnimatorLen; - break; + offset = -trackingAnimatorLen; + break; case ParagraphJustification::LeftJustify: - offset = 0.0f; - break; + offset = 0.0f; + break; default: - offset = -trackingAnimatorLen * 0.5f; - break; - } - return offset; + offset = -trackingAnimatorLen * 0.5f; + break; + } + return offset; } // 统计字符数目 static int CalculateCharactersCount(const std::vector>& glyphList) { - // 这里统计用于字间距的总字符数。 - // 对照AE里字间距范围选择器的统计规则:普通字符和空格计入统计、换行符不计入。 - // 此规则与glyphRunLines里的个数相同:glyphRunLines里也是换行符不进入列表 - // 为什么不用text的字符数,或者run->glyphIndex?因为它们是包括换行的,因此不符合 - int count = 0; - for (auto& line : glyphList) { - count += line.size(); - } - return count; + // 这里统计用于字间距的总字符数。 + // 对照AE里字间距范围选择器的统计规则:普通字符和空格计入统计、换行符不计入。 + // 此规则与glyphRunLines里的个数相同:glyphRunLines里也是换行符不进入列表 + // 为什么不用text的字符数,或者run->glyphIndex?因为它们是包括换行的,因此不符合 + int count = 0; + for (auto& line : glyphList) { + count += line.size(); + } + return count; } bool TextAnimatorRenderer::ApplyToGlyphs(std::vector>& glyphList, - const std::vector* animators, - const TextDocument* textDocument, Frame layerFrame) { - if (!HasAnimator(animators)) { - return false; // 提前判断如果没有文本动画,就不必要进行下面一堆操作了。 - } - int count = CalculateCharactersCount(glyphList); - if (count == 0) { - return false; // 如果字符数为0,则提前退出 - } - for (auto animator : *animators) { - TextAnimatorRenderer animatorRenderer(animator, textDocument, count, layerFrame); - animatorRenderer.apply(glyphList); - } - return true; + const std::vector* animators, + const TextDocument* textDocument, Frame layerFrame) { + if (!HasAnimator(animators)) { + return false; // 提前判断如果没有文本动画,就不必要进行下面一堆操作了。 + } + int count = CalculateCharactersCount(glyphList); + if (count == 0) { + return false; // 如果字符数为0,则提前退出 + } + for (auto animator : *animators) { + TextAnimatorRenderer animatorRenderer(animator, textDocument, count, layerFrame); + animatorRenderer.apply(glyphList); + } + return true; } // 根据序号获取文本动画位置(供AE导出插件在计算firstBaseLine时调用) Point TextAnimatorRenderer::GetPositionFromAnimators(const std::vector* animators, - const TextDocument* textDocument, - Frame layerFrame, size_t index, - bool* pBiasFlag) { - Point ret = {0.0f, 0.0f}; - *pBiasFlag = false; - if (animators != nullptr) { - for (auto animator : *animators) { - TextAnimatorRenderer animatorRenderer(animator, textDocument, textDocument->text.size(), - layerFrame); - bool biasFlag = false; - auto point = animatorRenderer.getPositionByIndex(index, &biasFlag); - *pBiasFlag |= biasFlag; - - ret.x += point.x; - ret.y += point.y; + const TextDocument* textDocument, + Frame layerFrame, size_t index, + bool* pBiasFlag) { + Point ret = {0.0f, 0.0f}; + *pBiasFlag = false; + if (animators != nullptr) { + for (auto animator : *animators) { + TextAnimatorRenderer animatorRenderer(animator, textDocument, textDocument->text.size(), + layerFrame); + bool biasFlag = false; + auto point = animatorRenderer.getPositionByIndex(index, &biasFlag); + *pBiasFlag |= biasFlag; + + ret.x += point.x; + ret.y += point.y; + } } - } - return ret; + return ret; } TextAnimatorRenderer::TextAnimatorRenderer(const TextAnimator* animator, - const TextDocument* textDocument, size_t textCount, - Frame frame) { - justification = textDocument->justification; - direction = textDocument->direction; - // 读取动画属性信息 - auto typographyProperties = animator->typographyProperties; - if (typographyProperties != nullptr) { - readTackingInfo(animator, frame); // 字间距 - - if (typographyProperties->position != nullptr) { - position = typographyProperties->position->getValueAt(frame); // 位置 - } - if (typographyProperties->scale != nullptr) { - scale = typographyProperties->scale->getValueAt(frame); // 缩放 - } - if (typographyProperties->rotation != nullptr) { - rotation = typographyProperties->rotation->getValueAt(frame); // 旋转 - } - if (typographyProperties->opacity != nullptr) { - opacity = typographyProperties->opacity->getValueAt(frame); // 不透明度 + const TextDocument* textDocument, size_t textCount, + Frame frame) { + justification = textDocument->justification; + direction = textDocument->direction; + // 读取动画属性信息 + auto typographyProperties = animator->typographyProperties; + if (typographyProperties != nullptr) { + readTackingInfo(animator, frame); // 字间距 + + if (typographyProperties->position != nullptr) { + position = typographyProperties->position->getValueAt(frame); // 位置 + } + if (typographyProperties->scale != nullptr) { + scale = typographyProperties->scale->getValueAt(frame); // 缩放 + } + if (typographyProperties->rotation != nullptr) { + rotation = typographyProperties->rotation->getValueAt(frame); // 旋转 + } + if (typographyProperties->opacity != nullptr) { + opacity = typographyProperties->opacity->getValueAt(frame); // 不透明度 + } } - } - - // 读取范围选择器信息 - for (auto selector : animator->selectors) { - if (selector->type() == TextSelectorType::Range) { - auto selectorRenderer = - new RangeSelectorRenderer(static_cast(selector), textCount, frame); - selectorRenderers.push_back(selectorRenderer); - } else if (selector->type() == TextSelectorType::Wiggly) { - auto selectorRenderer = - new WigglySelectorRenderer(static_cast(selector), textCount, frame); - selectorRenderers.push_back(selectorRenderer); + + // 读取范围选择器信息 + for (auto selector : animator->selectors) { + if (selector->type() == TextSelectorType::Range) { + auto selectorRenderer = + new RangeSelectorRenderer(static_cast(selector), textCount, frame); + selectorRenderers.push_back(selectorRenderer); + } else if (selector->type() == TextSelectorType::Wiggly) { + auto selectorRenderer = + new WigglySelectorRenderer(static_cast(selector), textCount, frame); + selectorRenderers.push_back(selectorRenderer); + } } - } } TextAnimatorRenderer::~TextAnimatorRenderer() { - for (auto selectorRenderer : selectorRenderers) { - delete selectorRenderer; - } + for (auto selectorRenderer : selectorRenderers) { + delete selectorRenderer; + } } // 读取字间距信息 void TextAnimatorRenderer::readTackingInfo(const TextAnimator* animator, Frame frame) { - if (animator->typographyProperties->trackingAmount != nullptr) { - auto trackingType = TextAnimatorTrackingType::BeforeAndAfter; - if (animator->typographyProperties->trackingType != nullptr) { - trackingType = animator->typographyProperties->trackingType->getValueAt(frame); - } - auto trackingAmount = animator->typographyProperties->trackingAmount->getValueAt(frame); - switch (trackingType) { - case TextAnimatorTrackingType::Before: - trackingBefore = trackingAmount; - trackingAfter = 0.0f; - break; - case TextAnimatorTrackingType::After: - trackingBefore = 0.0f; - trackingAfter = trackingAmount; - break; - default: // TextAnimatorTrackingType::AfterAndBefore - trackingBefore = trackingAmount * 0.5f; - trackingAfter = trackingAmount * 0.5f; - break; + if (animator->typographyProperties->trackingAmount != nullptr) { + auto trackingType = TextAnimatorTrackingType::BeforeAndAfter; + if (animator->typographyProperties->trackingType != nullptr) { + trackingType = animator->typographyProperties->trackingType->getValueAt(frame); + } + auto trackingAmount = animator->typographyProperties->trackingAmount->getValueAt(frame); + switch (trackingType) { + case TextAnimatorTrackingType::Before: + trackingBefore = trackingAmount; + trackingAfter = 0.0f; + break; + case TextAnimatorTrackingType::After: + trackingBefore = 0.0f; + trackingAfter = trackingAmount; + break; + default: // TextAnimatorTrackingType::AfterAndBefore + trackingBefore = trackingAmount * 0.5f; + trackingAfter = trackingAmount * 0.5f; + break; + } } - } } // 应用动画 void TextAnimatorRenderer::apply(std::vector>& glyphList) { - int index = 0; - for (auto& line : glyphList) { - int lineIndex = index; - int nextLineIndex = lineIndex + static_cast(line.size()); - auto trackingAnimatorLen = calculateTrackingLen(lineIndex, nextLineIndex); - auto offset = CalculateOffsetByJustification(justification, trackingAnimatorLen); - for (auto& glyph : line) { - auto matrix = glyph->getMatrix(); - auto factor = calculateFactorByIndex(index, nullptr); - // 字间距 - if (index > lineIndex) { // 行首不加字间距的before部分 - offset += trackingBefore * factor; - } - if (direction != TextDirection::Vertical) { - matrix.postTranslate(offset, 0); - } else { - matrix.postTranslate(0, offset); - } - offset += trackingAfter * factor; - - // 位置、缩放、旋转 - matrix.postTranslate(position.x * factor, position.y * factor); - matrix.preScale((scale.x - 1.0f) * factor + 1.0f, (scale.y - 1.0f) * factor + 1.0f); - matrix.preRotate(rotation * factor); - - // 透明度 - if (factor < 0.0f) { - factor = 0.0f; // 透明度的范围不能超过[0,1],所以限制factor不能为负。 - } - auto oldOpacity = glyph->getAlpha(); - auto opacityFactor = (opacity / 255.0f - 1.0f) * factor + 1.0f; - glyph->setAlpha(oldOpacity * opacityFactor); - - glyph->setMatrix(matrix); - index++; + int index = 0; + for (auto& line : glyphList) { + int lineIndex = index; + int nextLineIndex = lineIndex + static_cast(line.size()); + auto trackingAnimatorLen = calculateTrackingLen(lineIndex, nextLineIndex); + auto offset = CalculateOffsetByJustification(justification, trackingAnimatorLen); + for (auto& glyph : line) { + auto matrix = glyph->getMatrix(); + auto factor = calculateFactorByIndex(index, nullptr); + // 字间距 + if (index > lineIndex) { // 行首不加字间距的before部分 + offset += trackingBefore * factor; + } + if (direction != TextDirection::Vertical) { + matrix.postTranslate(offset, 0); + } else { + matrix.postTranslate(0, offset); + } + offset += trackingAfter * factor; + + // 位置、缩放、旋转 + matrix.postTranslate(position.x * factor, position.y * factor); + matrix.preScale((scale.x - 1.0f) * factor + 1.0f, (scale.y - 1.0f) * factor + 1.0f); + matrix.preRotate(rotation * factor); + + // 透明度 + if (factor < 0.0f) { + factor = 0.0f; // 透明度的范围不能超过[0,1],所以限制factor不能为负。 + } + auto oldOpacity = glyph->getAlpha(); + auto opacityFactor = (opacity / 255.0f - 1.0f) * factor + 1.0f; + glyph->setAlpha(oldOpacity * opacityFactor); + + glyph->setMatrix(matrix); + index++; + } } - } } // 计算一行的字间距长度 float TextAnimatorRenderer::calculateTrackingLen(size_t textStart, size_t textEnd) { - float animatorTrackingLen = 0.0f; - for (size_t i = textStart; i < textEnd; i++) { - auto factor = calculateFactorByIndex(i, nullptr); - if (i > textStart) { // 不计行首字母前面的间距 - animatorTrackingLen += trackingBefore * factor; - } - if (i < textEnd - 1) { // 不计行尾字母后面的间距 - animatorTrackingLen += trackingAfter * factor; + float animatorTrackingLen = 0.0f; + for (size_t i = textStart; i < textEnd; i++) { + auto factor = calculateFactorByIndex(i, nullptr); + if (i > textStart) { // 不计行首字母前面的间距 + animatorTrackingLen += trackingBefore * factor; + } + if (i < textEnd - 1) { // 不计行尾字母后面的间距 + animatorTrackingLen += trackingAfter * factor; + } } - } - return animatorTrackingLen; + return animatorTrackingLen; } // 计算某个字符的范围因子 float TextAnimatorRenderer::calculateFactorByIndex(size_t index, bool* pBiasFlag) { - return TextSelectorRenderer::CalculateFactorFromSelectors(selectorRenderers, index, pBiasFlag); + return TextSelectorRenderer::CalculateFactorFromSelectors(selectorRenderers, index, pBiasFlag); } // 根据序号获取位置(供AE导出插件在计算firstBaseLine时调用) Point TextAnimatorRenderer::getPositionByIndex(size_t index, bool* pBiasFlag) { - auto biasFlag = false; - auto factor = calculateFactorByIndex(index, &biasFlag); - if (biasFlag && (position.x != 0.0f || position.y != 0.0f)) { - *pBiasFlag = true; - } - return {position.x * factor, position.y * factor}; + auto biasFlag = false; + auto factor = calculateFactorByIndex(index, &biasFlag); + if (biasFlag && (position.x != 0.0f || position.y != 0.0f)) { + *pBiasFlag = true; + } + return {position.x * factor, position.y * factor}; } } // namespace pag diff --git a/src/rendering/renderers/TextAnimatorRenderer.h b/src/rendering/renderers/TextAnimatorRenderer.h index 268f486183..e811082995 100644 --- a/src/rendering/renderers/TextAnimatorRenderer.h +++ b/src/rendering/renderers/TextAnimatorRenderer.h @@ -25,45 +25,45 @@ namespace pag { class TextAnimatorRenderer { - public: - // 应用动画到Glyphs, 如果含有动画内容返回 true - static bool ApplyToGlyphs(std::vector>& glyphList, - const std::vector* animators, - const TextDocument* textDocument, Frame layerFrame); - // 根据序号获取文本动画位置(供AE导出插件在计算firstBaseLine时调用) - static Point GetPositionFromAnimators(const std::vector* animators, - const TextDocument* textDocument, Frame layerFrame, - size_t index, bool* pBiasFlag); - TextAnimatorRenderer(const TextAnimator* animator, const TextDocument* textDocument, - size_t textCount, Frame frame); - ~TextAnimatorRenderer(); +public: + // 应用动画到Glyphs, 如果含有动画内容返回 true + static bool ApplyToGlyphs(std::vector>& glyphList, + const std::vector* animators, + const TextDocument* textDocument, Frame layerFrame); + // 根据序号获取文本动画位置(供AE导出插件在计算firstBaseLine时调用) + static Point GetPositionFromAnimators(const std::vector* animators, + const TextDocument* textDocument, Frame layerFrame, + size_t index, bool* pBiasFlag); + TextAnimatorRenderer(const TextAnimator* animator, const TextDocument* textDocument, + size_t textCount, Frame frame); + ~TextAnimatorRenderer(); - private: - // 应用文本动画 - void apply(std::vector>& glyphList); - // 计算一行的字间距总长度 - float calculateTrackingLen(size_t textStart, size_t textEnd); - // 根据字符序号计算该字符的范围因子 - float calculateFactorByIndex(size_t index, bool* pBiasFlag); - // 读取字间距信息 - void readTackingInfo(const TextAnimator* animator, Frame frame); - // 根据序号获取位置(供AE导出插件在计算firstBaseLine时调用) - Point getPositionByIndex(size_t index, bool* pBiasFlag); +private: + // 应用文本动画 + void apply(std::vector>& glyphList); + // 计算一行的字间距总长度 + float calculateTrackingLen(size_t textStart, size_t textEnd); + // 根据字符序号计算该字符的范围因子 + float calculateFactorByIndex(size_t index, bool* pBiasFlag); + // 读取字间距信息 + void readTackingInfo(const TextAnimator* animator, Frame frame); + // 根据序号获取位置(供AE导出插件在计算firstBaseLine时调用) + Point getPositionByIndex(size_t index, bool* pBiasFlag); - // - // 动画属性:位置、缩放、旋转、不透明度、字间距 - // - Point position = Point::Zero(); // 位置 - Point scale = Point::Make(1, 1); // 缩放 - float rotation = 0.0f; // 旋转 - Opacity opacity = Opaque; // 不透明度,默认不透明 + // + // 动画属性:位置、缩放、旋转、不透明度、字间距 + // + Point position = Point::Zero(); // 位置 + Point scale = Point::Make(1, 1); // 缩放 + float rotation = 0.0f; // 旋转 + Opacity opacity = Opaque; // 不透明度,默认不透明 - float trackingBefore = 0.0f; // 字间距-之前 - float trackingAfter = 0.0f; // 字间距-之后 + float trackingBefore = 0.0f; // 字间距-之前 + float trackingAfter = 0.0f; // 字间距-之后 - Enum justification = ParagraphJustification::LeftJustify; - Enum direction = TextDirection::Default; + Enum justification = ParagraphJustification::LeftJustify; + Enum direction = TextDirection::Default; - std::vector selectorRenderers; + std::vector selectorRenderers; }; } // namespace pag diff --git a/src/rendering/renderers/TextRenderer.cpp b/src/rendering/renderers/TextRenderer.cpp index f83b6eef88..ea20697bb1 100644 --- a/src/rendering/renderers/TextRenderer.cpp +++ b/src/rendering/renderers/TextRenderer.cpp @@ -28,512 +28,512 @@ namespace pag { #define EMPTY_LINE_WIDTH 1.0f struct GlyphInfo { - int glyphIndex = 0; - std::string name; - float advance = 0; - Point position = Point::Zero(); - Rect bounds = Rect::MakeEmpty(); + int glyphIndex = 0; + std::string name; + float advance = 0; + Point position = Point::Zero(); + Rect bounds = Rect::MakeEmpty(); }; struct TextLayout { - float fontTop = 0; - float fontBottom = 0; - float lineGap = 0; - float tracking = 0; - float firstBaseLine = 0; - float baselineShift = 0; - Enum justification = 0; - Rect boxRect = Rect::MakeEmpty(); - float glyphScale = 1.0f; - Matrix coordinateMatrix = Matrix::I(); + float fontTop = 0; + float fontBottom = 0; + float lineGap = 0; + float tracking = 0; + float firstBaseLine = 0; + float baselineShift = 0; + Enum justification = 0; + Rect boxRect = Rect::MakeEmpty(); + float glyphScale = 1.0f; + Matrix coordinateMatrix = Matrix::I(); }; TextPaint CreateTextPaint(const TextDocument* textDocument) { - TextPaint textPaint = {}; - if (textDocument->applyFill && textDocument->applyStroke) { - textPaint.style = TextStyle::StrokeAndFill; - } else if (textDocument->applyStroke) { - textPaint.style = TextStyle::Stroke; - } else { - textPaint.style = TextStyle::Fill; - } - textPaint.fillColor = textDocument->fillColor; - textPaint.strokeColor = textDocument->strokeColor; - textPaint.strokeWidth = textDocument->strokeWidth; - textPaint.strokeOverFill = textDocument->strokeOverFill; - textPaint.fontFamily = textDocument->fontFamily; - textPaint.fontStyle = textDocument->fontStyle; - textPaint.fontSize = textDocument->fontSize; - textPaint.fauxBold = textDocument->fauxBold; - textPaint.fauxItalic = textDocument->fauxItalic; - textPaint.isVertical = textDocument->direction == TextDirection::Vertical; - return textPaint; + TextPaint textPaint = {}; + if (textDocument->applyFill && textDocument->applyStroke) { + textPaint.style = TextStyle::StrokeAndFill; + } else if (textDocument->applyStroke) { + textPaint.style = TextStyle::Stroke; + } else { + textPaint.style = TextStyle::Fill; + } + textPaint.fillColor = textDocument->fillColor; + textPaint.strokeColor = textDocument->strokeColor; + textPaint.strokeWidth = textDocument->strokeWidth; + textPaint.strokeOverFill = textDocument->strokeOverFill; + textPaint.fontFamily = textDocument->fontFamily; + textPaint.fontStyle = textDocument->fontStyle; + textPaint.fontSize = textDocument->fontSize; + textPaint.fauxBold = textDocument->fauxBold; + textPaint.fauxItalic = textDocument->fauxItalic; + textPaint.isVertical = textDocument->direction == TextDirection::Vertical; + return textPaint; } std::vector CreateGlyphInfos(const std::vector& glyphList) { - std::vector glyphInfos = {}; - int index = 0; - for (auto& glyph : glyphList) { - GlyphInfo info = {}; - info.glyphIndex = index++; - info.name = glyph->getName(); - info.advance = glyph->getAdvance(); - info.bounds = glyph->getBounds(); - // 当文本为竖版时,需要先转换为横排进行布局计算 - if (glyph->isVertical()) { - Matrix matrix = Matrix::I(); - matrix.setRotate(-90); - matrix.mapRect(&info.bounds); + std::vector glyphInfos = {}; + int index = 0; + for (auto& glyph : glyphList) { + GlyphInfo info = {}; + info.glyphIndex = index++; + info.name = glyph->getName(); + info.advance = glyph->getAdvance(); + info.bounds = glyph->getBounds(); + // 当文本为竖版时,需要先转换为横排进行布局计算 + if (glyph->isVertical()) { + Matrix matrix = Matrix::I(); + matrix.setRotate(-90); + matrix.mapRect(&info.bounds); + } + glyphInfos.push_back(info); } - glyphInfos.push_back(info); - } - return glyphInfos; + return glyphInfos; } TextLayout CreateTextLayout(const TextDocument* textDocument, const std::vector& glyphList) { - TextLayout layout = {}; - auto isVertical = textDocument->direction == TextDirection::Vertical; - if (!textDocument->boxText) { - layout.boxRect = Rect::MakeEmpty(); - if (isVertical) { - layout.coordinateMatrix.setRotate(90); - } - } else { - if (isVertical) { - auto boxRight = textDocument->boxTextPos.x + textDocument->boxTextSize.x; - layout.boxRect = - Rect::MakeXYWH(0, 0, textDocument->boxTextSize.y, textDocument->boxTextSize.x); - layout.firstBaseLine = boxRight - textDocument->firstBaseLine; - layout.coordinateMatrix.setRotate(90); - layout.coordinateMatrix.postTranslate(boxRight, textDocument->boxTextPos.y); + TextLayout layout = {}; + auto isVertical = textDocument->direction == TextDirection::Vertical; + if (!textDocument->boxText) { + layout.boxRect = Rect::MakeEmpty(); + if (isVertical) { + layout.coordinateMatrix.setRotate(90); + } } else { - layout.boxRect = - Rect::MakeXYWH(0, 0, textDocument->boxTextSize.x, textDocument->boxTextSize.y); - layout.firstBaseLine = textDocument->firstBaseLine - textDocument->boxTextPos.y; - layout.coordinateMatrix.setTranslate(textDocument->boxTextPos.x, textDocument->boxTextPos.y); + if (isVertical) { + auto boxRight = textDocument->boxTextPos.x + textDocument->boxTextSize.x; + layout.boxRect = + Rect::MakeXYWH(0, 0, textDocument->boxTextSize.y, textDocument->boxTextSize.x); + layout.firstBaseLine = boxRight - textDocument->firstBaseLine; + layout.coordinateMatrix.setRotate(90); + layout.coordinateMatrix.postTranslate(boxRight, textDocument->boxTextPos.y); + } else { + layout.boxRect = + Rect::MakeXYWH(0, 0, textDocument->boxTextSize.x, textDocument->boxTextSize.y); + layout.firstBaseLine = textDocument->firstBaseLine - textDocument->boxTextPos.y; + layout.coordinateMatrix.setTranslate(textDocument->boxTextPos.x, textDocument->boxTextPos.y); + } + } + layout.lineGap = textDocument->leading == 0 ? roundf(textDocument->fontSize * LINE_GAP_FACTOR) + : textDocument->leading; + layout.tracking = roundf(textDocument->tracking * textDocument->fontSize * 0.001f); + layout.baselineShift = textDocument->baselineShift; + layout.justification = textDocument->justification; + + float minAscent = 0, maxDescent = 0; + for (auto& glyph : glyphList) { + minAscent = std::min(minAscent, glyph->getAscent()); + maxDescent = std::max(maxDescent, glyph->getDescent()); } - } - layout.lineGap = textDocument->leading == 0 ? roundf(textDocument->fontSize * LINE_GAP_FACTOR) - : textDocument->leading; - layout.tracking = roundf(textDocument->tracking * textDocument->fontSize * 0.001f); - layout.baselineShift = textDocument->baselineShift; - layout.justification = textDocument->justification; - - float minAscent = 0, maxDescent = 0; - for (auto& glyph : glyphList) { - minAscent = std::min(minAscent, glyph->getAscent()); - maxDescent = std::max(maxDescent, glyph->getDescent()); - } - // 以 ascent 和 descent 比例计算出行高的上下位置。 - auto lineHeight = textDocument->fontSize * LINE_GAP_FACTOR; - layout.fontBottom = (maxDescent / (maxDescent - minAscent)) * lineHeight; - layout.fontTop = layout.fontBottom - lineHeight; - return layout; + // 以 ascent 和 descent 比例计算出行高的上下位置。 + auto lineHeight = textDocument->fontSize * LINE_GAP_FACTOR; + layout.fontBottom = (maxDescent / (maxDescent - minAscent)) * lineHeight; + layout.fontTop = layout.fontBottom - lineHeight; + return layout; } static size_t CalculateNextLineIndex(const std::vector& glyphList, size_t index, float scaleFactor, float maxWidth, float tracking, float* lineWidth) { - auto glyphCount = glyphList.size(); - *lineWidth = 0.0f; - bool hasPrevious = false; - while (index < glyphCount) { - auto& glyph = glyphList[index]; - index++; - *lineWidth += glyph.advance * scaleFactor; - - if (hasPrevious) { - *lineWidth += tracking; - } - hasPrevious = true; + auto glyphCount = glyphList.size(); + *lineWidth = 0.0f; + bool hasPrevious = false; + while (index < glyphCount) { + auto& glyph = glyphList[index]; + index++; + *lineWidth += glyph.advance * scaleFactor; + + if (hasPrevious) { + *lineWidth += tracking; + } + hasPrevious = true; - auto nextGlyphWidth = index < glyphCount ? glyphList[index].advance * scaleFactor : 0; - if (glyph.name[0] == '\n' || // line breaker. - *lineWidth + tracking + nextGlyphWidth > maxWidth) { - break; + auto nextGlyphWidth = index < glyphCount ? glyphList[index].advance * scaleFactor : 0; + if (glyph.name[0] == '\n' || // line breaker. + *lineWidth + tracking + nextGlyphWidth > maxWidth) { + break; + } } - } - return index; + return index; } static float CalculateGlyphScale(const TextLayout* layout, const std::vector& glyphInfos, float oldFontSize, float lineTop, float lineBottom, float visibleTop, float visibleBottom, float* totalTextLines) { - auto maxWidth = layout->boxRect.width(); - auto fontSize = oldFontSize; - while (fontSize > 5) { - bool canFit = true; - (*totalTextLines) = 0; - auto scaleFactor = fontSize / oldFontSize; - float baseLine = visibleTop - lineTop * scaleFactor; - float currentTracking = layout->tracking * scaleFactor; - float currentLineHeight = layout->lineGap * scaleFactor; - auto glyphCount = glyphInfos.size(); - size_t index = 0; - while (index < glyphCount) { - auto lineWidth = 0.0f; - index = CalculateNextLineIndex(glyphInfos, index, scaleFactor, maxWidth, currentTracking, - &lineWidth); - // baseline有可能超过boxRect的bottom,导致最后一行文字显示不出来 - if (baseLine + lineBottom * scaleFactor > visibleBottom || - baseLine > layout->boxRect.bottom) { - canFit = false; - break; - } - baseLine += currentLineHeight; - (*totalTextLines)++; - } - if (canFit) { - break; + auto maxWidth = layout->boxRect.width(); + auto fontSize = oldFontSize; + while (fontSize > 5) { + bool canFit = true; + (*totalTextLines) = 0; + auto scaleFactor = fontSize / oldFontSize; + float baseLine = visibleTop - lineTop * scaleFactor; + float currentTracking = layout->tracking * scaleFactor; + float currentLineHeight = layout->lineGap * scaleFactor; + auto glyphCount = glyphInfos.size(); + size_t index = 0; + while (index < glyphCount) { + auto lineWidth = 0.0f; + index = CalculateNextLineIndex(glyphInfos, index, scaleFactor, maxWidth, currentTracking, + &lineWidth); + // baseline有可能超过boxRect的bottom,导致最后一行文字显示不出来 + if (baseLine + lineBottom * scaleFactor > visibleBottom || + baseLine > layout->boxRect.bottom) { + canFit = false; + break; + } + baseLine += currentLineHeight; + (*totalTextLines)++; + } + if (canFit) { + break; + } + fontSize -= 1; } - fontSize -= 1; - } - return fontSize / oldFontSize; + return fontSize / oldFontSize; } static void AdjustToFitBox(TextLayout* layout, std::vector* glyphInfos, float fontSize) { - auto boxYOffset = layout->firstBaseLine - layout->boxRect.top; - auto boxTextLines = floorf((layout->boxRect.height() - boxYOffset) / layout->lineGap) + 1; - auto visibleTop = layout->firstBaseLine + layout->fontTop; - auto visibleBottom = - layout->firstBaseLine + layout->lineGap * (boxTextLines - 1) + layout->fontBottom; - float totalTextLines = 0; - auto scaleFactor = - CalculateGlyphScale(layout, *glyphInfos, fontSize, layout->fontTop, layout->fontBottom, - visibleTop, visibleBottom, &totalTextLines); - if (scaleFactor != 1) { - layout->glyphScale = scaleFactor; - layout->firstBaseLine = visibleTop + -layout->fontTop * scaleFactor; - if (totalTextLines == 1) { - layout->firstBaseLine += (1 - scaleFactor) * 0.5f * layout->lineGap; - } - layout->fontTop *= scaleFactor; - layout->fontBottom *= scaleFactor; - layout->tracking *= scaleFactor; - layout->lineGap *= scaleFactor; - for (auto& glyph : *glyphInfos) { - glyph.advance *= scaleFactor; - glyph.bounds.scale(scaleFactor, scaleFactor); - } - } else { - if (totalTextLines < boxTextLines) { - layout->firstBaseLine += (boxTextLines - totalTextLines) * layout->lineGap * 0.5f; + auto boxYOffset = layout->firstBaseLine - layout->boxRect.top; + auto boxTextLines = floorf((layout->boxRect.height() - boxYOffset) / layout->lineGap) + 1; + auto visibleTop = layout->firstBaseLine + layout->fontTop; + auto visibleBottom = + layout->firstBaseLine + layout->lineGap * (boxTextLines - 1) + layout->fontBottom; + float totalTextLines = 0; + auto scaleFactor = + CalculateGlyphScale(layout, *glyphInfos, fontSize, layout->fontTop, layout->fontBottom, + visibleTop, visibleBottom, &totalTextLines); + if (scaleFactor != 1) { + layout->glyphScale = scaleFactor; + layout->firstBaseLine = visibleTop + -layout->fontTop * scaleFactor; + if (totalTextLines == 1) { + layout->firstBaseLine += (1 - scaleFactor) * 0.5f * layout->lineGap; + } + layout->fontTop *= scaleFactor; + layout->fontBottom *= scaleFactor; + layout->tracking *= scaleFactor; + layout->lineGap *= scaleFactor; + for (auto& glyph : *glyphInfos) { + glyph.advance *= scaleFactor; + glyph.bounds.scale(scaleFactor, scaleFactor); + } + } else { + if (totalTextLines < boxTextLines) { + layout->firstBaseLine += (boxTextLines - totalTextLines) * layout->lineGap * 0.5f; + } } - } } static float CalculateDrawX(Enum justification, float lineWidth, bool isLastLine, const Rect& boxRect) { - float drawX; - - if (boxRect.isEmpty()) { - switch (justification) { - case ParagraphJustification::CenterJustify: - drawX = -lineWidth * 0.5f; - break; - case ParagraphJustification::RightJustify: - drawX = -lineWidth; - break; - default: - drawX = 0.0f; - break; + float drawX; + + if (boxRect.isEmpty()) { + switch (justification) { + case ParagraphJustification::CenterJustify: + drawX = -lineWidth * 0.5f; + break; + case ParagraphJustification::RightJustify: + drawX = -lineWidth; + break; + default: + drawX = 0.0f; + break; + } + return drawX; } - return drawX; - } - switch (justification) { + switch (justification) { case ParagraphJustification::CenterJustify: - drawX = boxRect.centerX() - lineWidth * 0.5f; - break; + drawX = boxRect.centerX() - lineWidth * 0.5f; + break; case ParagraphJustification::RightJustify: - drawX = boxRect.right - lineWidth; - break; + drawX = boxRect.right - lineWidth; + break; case ParagraphJustification::FullJustifyLastLineCenter: - if (isLastLine) { - drawX = boxRect.centerX() - lineWidth * 0.5f; - } else { - drawX = boxRect.left; - } - break; + if (isLastLine) { + drawX = boxRect.centerX() - lineWidth * 0.5f; + } else { + drawX = boxRect.left; + } + break; case ParagraphJustification::FullJustifyLastLineRight: - if (isLastLine) { - drawX = boxRect.right - lineWidth; - } else { - drawX = boxRect.left; - } - break; + if (isLastLine) { + drawX = boxRect.right - lineWidth; + } else { + drawX = boxRect.left; + } + break; default: - drawX = boxRect.left; - break; - } - return drawX; + drawX = boxRect.left; + break; + } + return drawX; } static float CalculateLetterSpacing(Enum justification, float tracking, float lineWidth, size_t lineGlyphCount, bool isLastLine, const Rect& boxRect) { - if (boxRect.isEmpty()) { - return tracking; - } - auto lastGlyphIndex = static_cast(lineGlyphCount - 1); - float justifyTracking = - (boxRect.width() - lineWidth + lastGlyphIndex * tracking) / lastGlyphIndex; - float letterSpacing; - switch (justification) { + if (boxRect.isEmpty()) { + return tracking; + } + auto lastGlyphIndex = static_cast(lineGlyphCount - 1); + float justifyTracking = + (boxRect.width() - lineWidth + lastGlyphIndex * tracking) / lastGlyphIndex; + float letterSpacing; + switch (justification) { case ParagraphJustification::FullJustifyLastLineLeft: case ParagraphJustification::FullJustifyLastLineCenter: case ParagraphJustification::FullJustifyLastLineRight: - if (isLastLine) { - letterSpacing = tracking; - } else { - letterSpacing = justifyTracking; - } - break; + if (isLastLine) { + letterSpacing = tracking; + } else { + letterSpacing = justifyTracking; + } + break; case ParagraphJustification::FullJustifyLastLineFull: - letterSpacing = justifyTracking; - break; + letterSpacing = justifyTracking; + break; default: - letterSpacing = tracking; - break; - } - return letterSpacing; + letterSpacing = tracking; + break; + } + return letterSpacing; } static std::vector> ApplyLayoutToGlyphInfos( - const TextLayout& layout, std::vector* glyphInfos, Rect* bounds) { - float maxWidth, maxY; - if (layout.boxRect.isEmpty()) { - maxWidth = std::numeric_limits::infinity(); - maxY = std::numeric_limits::infinity(); - } else { - maxWidth = layout.boxRect.width(); - maxY = layout.boxRect.bottom; - } - - std::vector> lineList = {}; - auto glyphCount = glyphInfos->size(); - size_t index = 0; - int lineIndex = 0; - auto baseLine = layout.firstBaseLine; - while (index < glyphCount) { - if (baseLine > maxY) { - break; - } - auto lineGlyphStart = index; - auto lineWidth = 0.0f; - auto nextLineIndex = - CalculateNextLineIndex(*glyphInfos, index, 1.0f, maxWidth, layout.tracking, &lineWidth); - auto hasLineBreaker = (*glyphInfos)[nextLineIndex - 1].name[0] == '\n'; // 换行符 - auto lineGlyphEnd = nextLineIndex - (hasLineBreaker ? 1 : 0); - index = nextLineIndex; - bool isLastLine = (index == glyphCount); - auto drawX = CalculateDrawX(layout.justification, lineWidth, isLastLine || hasLineBreaker, - layout.boxRect); - auto drawY = baseLine - layout.baselineShift; - float letterSpacing = CalculateLetterSpacing(layout.justification, layout.tracking, lineWidth, - lineGlyphEnd - lineGlyphStart, - isLastLine || hasLineBreaker, layout.boxRect); - std::vector glyphLine = {}; - for (size_t i = lineGlyphStart; i < lineGlyphEnd; i++) { - auto& glyph = (*glyphInfos)[i]; - glyph.position.x = drawX; - glyph.position.y = drawY; - glyph.bounds.offset(drawX, drawY); - glyphLine.push_back(&glyph); - bounds->join(glyph.bounds); - drawX += glyph.advance + letterSpacing; - } - if (!glyphLine.empty()) { - lineList.push_back(glyphLine); +const TextLayout& layout, std::vector* glyphInfos, Rect* bounds) { + float maxWidth, maxY; + if (layout.boxRect.isEmpty()) { + maxWidth = std::numeric_limits::infinity(); + maxY = std::numeric_limits::infinity(); } else { - auto emptyLineBounds = Rect::MakeLTRB(drawX, drawY + layout.fontTop, drawX + EMPTY_LINE_WIDTH, - drawY + layout.fontBottom); - bounds->join(emptyLineBounds); + maxWidth = layout.boxRect.width(); + maxY = layout.boxRect.bottom; } - baseLine += layout.lineGap; - lineIndex++; - } - return lineList; + std::vector> lineList = {}; + auto glyphCount = glyphInfos->size(); + size_t index = 0; + int lineIndex = 0; + auto baseLine = layout.firstBaseLine; + while (index < glyphCount) { + if (baseLine > maxY) { + break; + } + auto lineGlyphStart = index; + auto lineWidth = 0.0f; + auto nextLineIndex = + CalculateNextLineIndex(*glyphInfos, index, 1.0f, maxWidth, layout.tracking, &lineWidth); + auto hasLineBreaker = (*glyphInfos)[nextLineIndex - 1].name[0] == '\n'; // 换行符 + auto lineGlyphEnd = nextLineIndex - (hasLineBreaker ? 1 : 0); + index = nextLineIndex; + bool isLastLine = (index == glyphCount); + auto drawX = CalculateDrawX(layout.justification, lineWidth, isLastLine || hasLineBreaker, + layout.boxRect); + auto drawY = baseLine - layout.baselineShift; + float letterSpacing = CalculateLetterSpacing(layout.justification, layout.tracking, lineWidth, + lineGlyphEnd - lineGlyphStart, + isLastLine || hasLineBreaker, layout.boxRect); + std::vector glyphLine = {}; + for (size_t i = lineGlyphStart; i < lineGlyphEnd; i++) { + auto& glyph = (*glyphInfos)[i]; + glyph.position.x = drawX; + glyph.position.y = drawY; + glyph.bounds.offset(drawX, drawY); + glyphLine.push_back(&glyph); + bounds->join(glyph.bounds); + drawX += glyph.advance + letterSpacing; + } + if (!glyphLine.empty()) { + lineList.push_back(glyphLine); + } else { + auto emptyLineBounds = Rect::MakeLTRB(drawX, drawY + layout.fontTop, drawX + EMPTY_LINE_WIDTH, + drawY + layout.fontBottom); + bounds->join(emptyLineBounds); + } + baseLine += layout.lineGap; + + lineIndex++; + } + return lineList; } static std::vector> ApplyMatrixToGlyphs( - const TextLayout& layout, const std::vector>& glyphInfoLines, - std::vector* glyphList) { - std::vector> glyphLines = {}; - for (auto& line : glyphInfoLines) { - std::vector glyphLine = {}; - for (auto& info : line) { - auto& glyph = (*glyphList)[info->glyphIndex]; - auto matrix = Matrix::MakeScale(layout.glyphScale); - auto pos = info->position; - layout.coordinateMatrix.mapPoints(&pos, 1); - matrix.postTranslate(pos.x, pos.y); - glyph->setMatrix(matrix); - glyphLine.push_back(glyph); - } - if (!glyphLine.empty()) { - glyphLines.push_back(glyphLine); + const TextLayout& layout, const std::vector>& glyphInfoLines, +std::vector* glyphList) { + std::vector> glyphLines = {}; + for (auto& line : glyphInfoLines) { + std::vector glyphLine = {}; + for (auto& info : line) { + auto& glyph = (*glyphList)[info->glyphIndex]; + auto matrix = Matrix::MakeScale(layout.glyphScale); + auto pos = info->position; + layout.coordinateMatrix.mapPoints(&pos, 1); + matrix.postTranslate(pos.x, pos.y); + glyph->setMatrix(matrix); + glyphLine.push_back(glyph); + } + if (!glyphLine.empty()) { + glyphLines.push_back(glyphLine); + } } - } - return glyphLines; + return glyphLines; } static Path RenderBackgroundPath(const std::vector>& glyphLines, float margin, float lineTop, float lineBottom, bool isVertical) { - Path backgroundPath = {}; - std::vector lineRectList = {}; - for (auto& line : glyphLines) { - Rect lineRect = Rect::MakeEmpty(); - for (auto& glyph : line) { - Rect textBounds = {}; - if (isVertical) { - textBounds = Rect::MakeLTRB(-lineBottom, 0, -lineTop, glyph->getAdvance()); - } else { - textBounds = Rect::MakeLTRB(0, lineTop, glyph->getAdvance(), lineBottom); - } - glyph->getMatrix().mapRect(&textBounds); - lineRect.join(textBounds); - } - if (!lineRect.isEmpty()) { - lineRect.outset(margin, margin); - lineRectList.push_back(lineRect); - } - } - auto lineCount = static_cast(lineRectList.size()); - float topInset = 0, bottomInset = 0, leftInset = 0, rightInset = 0; - for (int i = 0; i < lineCount; i++) { - auto& lineRect = lineRectList[i]; - if (i < lineCount - 1) { - auto nextLineRect = lineRectList[i + 1]; - if (isVertical) { - if (lineRect.left > nextLineRect.right) { - leftInset = (lineRect.left - nextLineRect.right) * 0.5f; - } else { - leftInset = 0; + Path backgroundPath = {}; + std::vector lineRectList = {}; + for (auto& line : glyphLines) { + Rect lineRect = Rect::MakeEmpty(); + for (auto& glyph : line) { + Rect textBounds = {}; + if (isVertical) { + textBounds = Rect::MakeLTRB(-lineBottom, 0, -lineTop, glyph->getAdvance()); + } else { + textBounds = Rect::MakeLTRB(0, lineTop, glyph->getAdvance(), lineBottom); + } + glyph->getMatrix().mapRect(&textBounds); + lineRect.join(textBounds); } - } else { - if (lineRect.bottom < nextLineRect.top) { - bottomInset = (nextLineRect.top - lineRect.bottom) * 0.5f; - } else { - bottomInset = 0; + if (!lineRect.isEmpty()) { + lineRect.outset(margin, margin); + lineRectList.push_back(lineRect); + } + } + auto lineCount = static_cast(lineRectList.size()); + float topInset = 0, bottomInset = 0, leftInset = 0, rightInset = 0; + for (int i = 0; i < lineCount; i++) { + auto& lineRect = lineRectList[i]; + if (i < lineCount - 1) { + auto nextLineRect = lineRectList[i + 1]; + if (isVertical) { + if (lineRect.left > nextLineRect.right) { + leftInset = (lineRect.left - nextLineRect.right) * 0.5f; + } else { + leftInset = 0; + } + } else { + if (lineRect.bottom < nextLineRect.top) { + bottomInset = (nextLineRect.top - lineRect.bottom) * 0.5f; + } else { + bottomInset = 0; + } + } } - } + lineRect.left -= leftInset; + lineRect.right += rightInset; + lineRect.top -= topInset; + lineRect.bottom += bottomInset; + topInset = bottomInset; // 下一行的topInset是上一行的bottomInset. + rightInset = leftInset; + Path tempPath = {}; + // 必须round一下避开浮点计算误差,规避 Path 合并的 Bug,否则得到中间断开的不连续矩形。 + lineRect.round(); + tempPath.addRect(lineRect); + backgroundPath.addPath(tempPath); } - lineRect.left -= leftInset; - lineRect.right += rightInset; - lineRect.top -= topInset; - lineRect.bottom += bottomInset; - topInset = bottomInset; // 下一行的topInset是上一行的bottomInset. - rightInset = leftInset; - Path tempPath = {}; - // 必须round一下避开浮点计算误差,规避 Path 合并的 Bug,否则得到中间断开的不连续矩形。 - lineRect.round(); - tempPath.addRect(lineRect); - backgroundPath.addPath(tempPath); - } - return backgroundPath; + return backgroundPath; } std::shared_ptr RenderTextBackground(const std::vector>& lines, - const TextDocument* textDocument) { - float strokeWidth = textDocument->strokeWidth; - auto margin = textDocument->fontSize * 0.2f; - if (margin < strokeWidth) { - margin = strokeWidth; - } - auto isVertical = textDocument->direction == TextDirection::Vertical; - float lineTop = 0, lineBottom = 0; - for (auto& line : lines) { - for (auto& glyph : line) { - if (isVertical) { - lineTop = std::min(lineTop, -glyph->getBounds().right); - lineBottom = std::max(lineBottom, -glyph->getBounds().left); - } else { - lineTop = std::min(lineTop, glyph->getBounds().top); - lineBottom = std::max(lineBottom, glyph->getBounds().bottom); - } + const TextDocument* textDocument) { + float strokeWidth = textDocument->strokeWidth; + auto margin = textDocument->fontSize * 0.2f; + if (margin < strokeWidth) { + margin = strokeWidth; + } + auto isVertical = textDocument->direction == TextDirection::Vertical; + float lineTop = 0, lineBottom = 0; + for (auto& line : lines) { + for (auto& glyph : line) { + if (isVertical) { + lineTop = std::min(lineTop, -glyph->getBounds().right); + lineBottom = std::max(lineBottom, -glyph->getBounds().left); + } else { + lineTop = std::min(lineTop, glyph->getBounds().top); + lineBottom = std::max(lineBottom, glyph->getBounds().bottom); + } + } } - } - - auto backgroundPath = RenderBackgroundPath(lines, margin, lineTop, lineBottom, isVertical); - auto bounds = backgroundPath.getBounds(); - float maxRadius = std::min(bounds.width(), bounds.height()) / 3.0f; - if (maxRadius >= 25.0f) { - maxRadius = 25.0f; - } - auto effect = PathEffect::MakeCorner(maxRadius); - if (effect) { - effect->applyTo(&backgroundPath); - } - auto graphic = Shape::MakeFrom(backgroundPath, textDocument->backgroundColor); - auto modifier = Modifier::MakeBlend(textDocument->backgroundAlpha, BlendMode::Normal); - return Graphic::MakeCompose(graphic, modifier); + + auto backgroundPath = RenderBackgroundPath(lines, margin, lineTop, lineBottom, isVertical); + auto bounds = backgroundPath.getBounds(); + float maxRadius = std::min(bounds.width(), bounds.height()) / 3.0f; + if (maxRadius >= 25.0f) { + maxRadius = 25.0f; + } + auto effect = PathEffect::MakeCorner(maxRadius); + if (effect) { + effect->applyTo(&backgroundPath); + } + auto graphic = Shape::MakeFrom(backgroundPath, textDocument->backgroundColor); + auto modifier = Modifier::MakeBlend(textDocument->backgroundAlpha, BlendMode::Normal); + return Graphic::MakeCompose(graphic, modifier); } std::unique_ptr RenderTexts(Property* sourceText, TextPathOptions*, - TextMoreOptions*, std::vector* animators, - Frame layerFrame) { - auto textDocument = sourceText->getValueAt(layerFrame); - auto textPaint = CreateTextPaint(textDocument.get()); - auto glyphList = Glyph::BuildFromText(textDocument->text, textPaint); - // 无论文字朝向,都先按从(0,0)点开始的横向矩形排版。 - // 提取出跟文字朝向无关的 GlyphInfo 列表与 TextLayout, - // 复用同一套排版规则。如果最终是纵向排版,再把坐标转成纵向坐标应用到 glyphList 上。 - auto glyphInfos = CreateGlyphInfos(glyphList); - auto textLayout = CreateTextLayout(textDocument.get(), glyphList); - if (textDocument->boxText) { - AdjustToFitBox(&textLayout, &glyphInfos, textDocument->fontSize); - } - Rect textBounds = Rect::MakeEmpty(); - auto glyphInfoLines = ApplyLayoutToGlyphInfos(textLayout, &glyphInfos, &textBounds); - auto glyphLines = ApplyMatrixToGlyphs(textLayout, glyphInfoLines, &glyphList); - textLayout.coordinateMatrix.mapRect(&textBounds); - auto hasAnimators = - TextAnimatorRenderer::ApplyToGlyphs(glyphLines, animators, textDocument.get(), layerFrame); - std::vector> contents = {}; - if (textDocument->backgroundAlpha > 0) { - auto background = RenderTextBackground(glyphLines, textDocument.get()); - if (background) { - contents.push_back(background); + TextMoreOptions*, std::vector* animators, + Frame layerFrame) { + auto textDocument = sourceText->getValueAt(layerFrame); + auto textPaint = CreateTextPaint(textDocument.get()); + auto glyphList = Glyph::BuildFromText(textDocument->text, textPaint); + // 无论文字朝向,都先按从(0,0)点开始的横向矩形排版。 + // 提取出跟文字朝向无关的 GlyphInfo 列表与 TextLayout, + // 复用同一套排版规则。如果最终是纵向排版,再把坐标转成纵向坐标应用到 glyphList 上。 + auto glyphInfos = CreateGlyphInfos(glyphList); + auto textLayout = CreateTextLayout(textDocument.get(), glyphList); + if (textDocument->boxText) { + AdjustToFitBox(&textLayout, &glyphInfos, textDocument->fontSize); } - } - - std::vector simpleGlyphs = {}; - std::vector colorGlyphs = {}; - for (auto& line : glyphLines) { - for (auto& glyph : line) { - simpleGlyphs.push_back(glyph); - auto typeface = glyph->getFont().getTypeface(); - if (typeface->hasColor()) { - colorGlyphs.push_back(glyph); - } + Rect textBounds = Rect::MakeEmpty(); + auto glyphInfoLines = ApplyLayoutToGlyphInfos(textLayout, &glyphInfos, &textBounds); + auto glyphLines = ApplyMatrixToGlyphs(textLayout, glyphInfoLines, &glyphList); + textLayout.coordinateMatrix.mapRect(&textBounds); + auto hasAnimators = + TextAnimatorRenderer::ApplyToGlyphs(glyphLines, animators, textDocument.get(), layerFrame); + std::vector> contents = {}; + if (textDocument->backgroundAlpha > 0) { + auto background = RenderTextBackground(glyphLines, textDocument.get()); + if (background) { + contents.push_back(background); + } } - } - - auto normalText = Text::MakeFrom(simpleGlyphs, hasAnimators ? nullptr : &textBounds); - if (normalText) { - contents.push_back(normalText); - } - auto graphic = Graphic::MakeCompose(contents); - auto colorText = Text::MakeFrom(colorGlyphs); - return std::unique_ptr(new TextContent(std::move(graphic), std::move(colorText))); + + std::vector simpleGlyphs = {}; + std::vector colorGlyphs = {}; + for (auto& line : glyphLines) { + for (auto& glyph : line) { + simpleGlyphs.push_back(glyph); + auto typeface = glyph->getFont().getTypeface(); + if (typeface->hasColor()) { + colorGlyphs.push_back(glyph); + } + } + } + + auto normalText = Text::MakeFrom(simpleGlyphs, hasAnimators ? nullptr : &textBounds); + if (normalText) { + contents.push_back(normalText); + } + auto graphic = Graphic::MakeCompose(contents); + auto colorText = Text::MakeFrom(colorGlyphs); + return std::unique_ptr(new TextContent(std::move(graphic), std::move(colorText))); } void CalculateTextAscentAndDescent(TextDocumentHandle textDocument, float* pMinAscent, float* pMaxDescent) { - auto textPaint = CreateTextPaint(textDocument.get()); - auto glyphList = Glyph::BuildFromText(textDocument->text, textPaint); - - float minAscent = 0; - float maxDescent = 0; - for (auto& glyph : glyphList) { - minAscent = std::min(minAscent, glyph->getAscent()); - maxDescent = std::max(maxDescent, glyph->getDescent()); - } - - *pMinAscent = minAscent; - *pMaxDescent = maxDescent; + auto textPaint = CreateTextPaint(textDocument.get()); + auto glyphList = Glyph::BuildFromText(textDocument->text, textPaint); + + float minAscent = 0; + float maxDescent = 0; + for (auto& glyph : glyphList) { + minAscent = std::min(minAscent, glyph->getAscent()); + maxDescent = std::max(maxDescent, glyph->getDescent()); + } + + *pMinAscent = minAscent; + *pMaxDescent = maxDescent; } } // namespace pag diff --git a/src/rendering/renderers/TextRenderer.h b/src/rendering/renderers/TextRenderer.h index b15a5bc9e0..2c83a1657f 100644 --- a/src/rendering/renderers/TextRenderer.h +++ b/src/rendering/renderers/TextRenderer.h @@ -25,8 +25,8 @@ namespace pag { std::unique_ptr RenderTexts(Property* sourceText, - TextPathOptions* pathOption, TextMoreOptions* moreOption, - std::vector* animators, Frame layerFrame); + TextPathOptions* pathOption, TextMoreOptions* moreOption, + std::vector* animators, Frame layerFrame); void CalculateTextAscentAndDescent(TextDocumentHandle textDocument, float* pMinAscent, float* pMaxDescent); diff --git a/src/rendering/renderers/TextSelectorRenderer.cpp b/src/rendering/renderers/TextSelectorRenderer.cpp index 2bc5b9d3ea..5b35d60452 100644 --- a/src/rendering/renderers/TextSelectorRenderer.cpp +++ b/src/rendering/renderers/TextSelectorRenderer.cpp @@ -23,65 +23,65 @@ namespace pag { float TextSelectorRenderer::CalculateFactorFromSelectors( const std::vector& selectorRenderers, size_t index, bool* pBiasFlag) { - float totalFactor = 1.0f; - bool isFirstSelector = true; - for (auto selectorRenderer : selectorRenderers) { - bool biasFlag = false; - auto factor = selectorRenderer->calculateFactorByIndex(index, &biasFlag); - if (pBiasFlag != nullptr) { - *pBiasFlag |= biasFlag; + float totalFactor = 1.0f; + bool isFirstSelector = true; + for (auto selectorRenderer : selectorRenderers) { + bool biasFlag = false; + auto factor = selectorRenderer->calculateFactorByIndex(index, &biasFlag); + if (pBiasFlag != nullptr) { + *pBiasFlag |= biasFlag; + } + totalFactor = selectorRenderer->overlayFactor(totalFactor, factor, isFirstSelector); + isFirstSelector = false; } - totalFactor = selectorRenderer->overlayFactor(totalFactor, factor, isFirstSelector); - isFirstSelector = false; - } - return totalFactor; + return totalFactor; } static float OverlayFactorByMode(float oldFactor, float factor, Enum mode) { - float newFactor; - switch (mode) { + float newFactor; + switch (mode) { case TextSelectorMode::Subtract: - if (factor >= 0.0f) { - newFactor = oldFactor * (1.0f - factor); - } else { - newFactor = oldFactor * (-1.0f - factor); - } - break; + if (factor >= 0.0f) { + newFactor = oldFactor * (1.0f - factor); + } else { + newFactor = oldFactor * (-1.0f - factor); + } + break; case TextSelectorMode::Intersect: - newFactor = oldFactor * factor; - break; + newFactor = oldFactor * factor; + break; case TextSelectorMode::Min: - newFactor = std::min(oldFactor, factor); - break; + newFactor = std::min(oldFactor, factor); + break; case TextSelectorMode::Max: - newFactor = std::max(oldFactor, factor); - break; + newFactor = std::max(oldFactor, factor); + break; case TextSelectorMode::Difference: - newFactor = fabs(oldFactor - factor); - break; + newFactor = fabs(oldFactor - factor); + break; default: // TextSelectorMode::Add: - newFactor = oldFactor + factor; - break; - } - return newFactor; + newFactor = oldFactor + factor; + break; + } + return newFactor; } // 叠加选择器 float TextSelectorRenderer::overlayFactor(float oldFactor, float factor, bool isFirstSelector) { - auto newFactor = 0.0f; - if (isFirstSelector && mode != TextSelectorMode::Subtract) { - // 首次且叠加模式不为Subtract时,直接取factor - // 首次且叠加模式为Subtract时,合并入OverlayFactorByMode计算。(首次时oldFactor外部默认为1.0f) - newFactor = factor; - } else { - newFactor = OverlayFactorByMode(oldFactor, factor, mode); - } - if (newFactor < -1.0f) { - newFactor = -1.0f; - } else if (newFactor > 1.0f) { - newFactor = 1.0f; - } - return newFactor; + auto newFactor = 0.0f; + if (isFirstSelector && mode != TextSelectorMode::Subtract) { + // 首次且叠加模式不为Subtract时,直接取factor + // 首次且叠加模式为Subtract时,合并入OverlayFactorByMode计算。(首次时oldFactor外部默认为1.0f) + newFactor = factor; + } else { + newFactor = OverlayFactorByMode(oldFactor, factor, mode); + } + if (newFactor < -1.0f) { + newFactor = -1.0f; + } else if (newFactor > 1.0f) { + newFactor = 1.0f; + } + return newFactor; } // @@ -94,8 +94,8 @@ float TextSelectorRenderer::overlayFactor(float oldFactor, float factor, bool is // 其中,因start可以通过上一个end+1获取,所以表里忽略start,仅有end和index。 // static const struct { - int end; - int index; + int end; + int index; } randomRanges[] = { {2, 0}, // [1,2] = 0 {4, 2}, // [3,4] = 2 @@ -108,302 +108,304 @@ static const struct { }; static int GetRandomIndex(int textCount) { - for (size_t i = 0; i < sizeof(randomRanges) / sizeof(randomRanges[0]); i++) { - if (textCount <= randomRanges[i].end) { - return randomRanges[i].index; + for (size_t i = 0; i < sizeof(randomRanges) / sizeof(randomRanges[0]); i++) { + if (textCount <= randomRanges[i].end) { + return randomRanges[i].index; + } } - } - return 0; + return 0; } void TextSelectorRenderer::calculateRandomIndexs(uint16_t seed) { - srand(seed); // 重置随机种子 - std::vector> randList; - for (size_t i = 0; i < textCount; i++) { - randList.push_back(std::make_pair(rand(), i)); // 生成随机数 - } + srand(seed); // 重置随机种子 + std::vector> randList; + for (size_t i = 0; i < textCount; i++) { + randList.push_back(std::make_pair(rand(), i)); // 生成随机数 + } - // 排序 - std::sort(std::begin(randList), std::end(randList), - [](const std::pair& a, std::pair& b) { return a.first < b.first; }); + // 排序 + std::sort(std::begin(randList), std::end(randList), + [](const std::pair& a, std::pair& b) { + return a.first < b.first; + }); - // 随机数排序后的序号作为真正的顺序 - for (size_t i = 0; i < textCount; i++) { - randomIndexs.push_back(randList[i].second); - } + // 随机数排序后的序号作为真正的顺序 + for (size_t i = 0; i < textCount; i++) { + randomIndexs.push_back(randList[i].second); + } - if (seed == 0 && textCount > 1) { - // 查表获取位置0的随机序号m - // 同时,为了避免序号冲突,需要再把0原本的序号赋值给原本取值为m的位置k - auto m = GetRandomIndex(static_cast(textCount)); - size_t k = 0; - do { - if (randomIndexs[k] == m) { - break; - } - } while (++k < textCount); - std::swap(randomIndexs[0], randomIndexs[k]); - } + if (seed == 0 && textCount > 1) { + // 查表获取位置0的随机序号m + // 同时,为了避免序号冲突,需要再把0原本的序号赋值给原本取值为m的位置k + auto m = GetRandomIndex(static_cast(textCount)); + size_t k = 0; + do { + if (randomIndexs[k] == m) { + break; + } + } while (++k < textCount); + std::swap(randomIndexs[0], randomIndexs[k]); + } } // 读取摆动选择器 WigglySelectorRenderer::WigglySelectorRenderer(const TextWigglySelector* selector, size_t textCount, - Frame frame) + Frame frame) : TextSelectorRenderer(textCount, frame) { - // 获取属性:模式、最大量、最小量 - mode = selector->mode->getValueAt(frame); // 模式 - maxAmount = selector->maxAmount->getValueAt(frame); // 数量 - minAmount = selector->minAmount->getValueAt(frame); // 数量 - wigglesPerSecond = selector->wigglesPerSecond->getValueAt(frame); // 摇摆/秒 - correlation = selector->correlation->getValueAt(frame); // 关联 - temporalPhase = selector->temporalPhase->getValueAt(frame); // 时间相位 - spatialPhase = selector->spatialPhase->getValueAt(frame); // 空间相位 - randomSeed = selector->randomSeed->getValueAt(frame); // 随机植入 + // 获取属性:模式、最大量、最小量 + mode = selector->mode->getValueAt(frame); // 模式 + maxAmount = selector->maxAmount->getValueAt(frame); // 数量 + minAmount = selector->minAmount->getValueAt(frame); // 数量 + wigglesPerSecond = selector->wigglesPerSecond->getValueAt(frame); // 摇摆/秒 + correlation = selector->correlation->getValueAt(frame); // 关联 + temporalPhase = selector->temporalPhase->getValueAt(frame); // 时间相位 + spatialPhase = selector->spatialPhase->getValueAt(frame); // 空间相位 + randomSeed = selector->randomSeed->getValueAt(frame); // 随机植入 } // 计算摆动选择器中某个字符的范围因子 float WigglySelectorRenderer::calculateFactorByIndex(size_t index, bool* pBiasFlag) { - if (textCount == 0) { - return 0.0f; - } + if (textCount == 0) { + return 0.0f; + } - // 这里的公式离复原AE效果还有一定的距离。后续可优化。 - // 经验值也需要优化. - auto temporalSeed = wigglesPerSecond / 2.0 * (frame + temporalPhase / 30.f) / 24.0f; - auto spatialSeed = (13.73f * (1.0f - correlation) * index + spatialPhase / 80.0f) / 21.13f; - auto seed = (spatialSeed + temporalSeed + randomSeed / 3.13f) * 2 * M_PI; - auto factor = cos(seed) * cos(seed / 7 + M_PI / 5); - if (factor < -1.0f) { - factor = -1.0f; - } else if (factor > 1.0f) { - factor = 1.0f; - } + // 这里的公式离复原AE效果还有一定的距离。后续可优化。 + // 经验值也需要优化. + auto temporalSeed = wigglesPerSecond / 2.0 * (frame + temporalPhase / 30.f) / 24.0f; + auto spatialSeed = (13.73f * (1.0f - correlation) * index + spatialPhase / 80.0f) / 21.13f; + auto seed = (spatialSeed + temporalSeed + randomSeed / 3.13f) * 2 * M_PI; + auto factor = cos(seed) * cos(seed / 7 + M_PI / 5); + if (factor < -1.0f) { + factor = -1.0f; + } else if (factor > 1.0f) { + factor = 1.0f; + } - // 考虑"最大量"/"最小量"的影响 - factor = (factor + 1.0f) / 2 * (maxAmount - minAmount) + minAmount; - if (pBiasFlag != nullptr) { - *pBiasFlag = true; // 摆动选择器计算有误差 - } - return factor; + // 考虑"最大量"/"最小量"的影响 + factor = (factor + 1.0f) / 2 * (maxAmount - minAmount) + minAmount; + if (pBiasFlag != nullptr) { + *pBiasFlag = true; // 摆动选择器计算有误差 + } + return factor; } // 读取范围选择器 RangeSelectorRenderer::RangeSelectorRenderer(const TextRangeSelector* selector, size_t textCount, - Frame frame) + Frame frame) : TextSelectorRenderer(textCount, frame) { - // 获取基础属性:开始、结束、偏移 - rangeStart = selector->start->getValueAt(frame); // 开始 - rangeEnd = selector->end->getValueAt(frame); // 结束 - auto offset = selector->offset->getValueAt(frame); // 偏移 - rangeStart += offset; - rangeEnd += offset; - if (rangeStart > rangeEnd) { // 如果开始比结束大,则调换,方便后续处理 - std::swap(rangeStart, rangeEnd); - } + // 获取基础属性:开始、结束、偏移 + rangeStart = selector->start->getValueAt(frame); // 开始 + rangeEnd = selector->end->getValueAt(frame); // 结束 + auto offset = selector->offset->getValueAt(frame); // 偏移 + rangeStart += offset; + rangeEnd += offset; + if (rangeStart > rangeEnd) { // 如果开始比结束大,则调换,方便后续处理 + std::swap(rangeStart, rangeEnd); + } - // 获取高级属性:模式、数量、形状、随机排序 - mode = selector->mode->getValueAt(frame); // 模式 - amount = selector->amount->getValueAt(frame); // 数量 - shape = selector->shape; // 形状 - randomizeOrder = selector->randomizeOrder; // 随机排序 - randomSeed = selector->randomSeed->getValueAt(frame); // 随机植入 + // 获取高级属性:模式、数量、形状、随机排序 + mode = selector->mode->getValueAt(frame); // 模式 + amount = selector->amount->getValueAt(frame); // 数量 + shape = selector->shape; // 形状 + randomizeOrder = selector->randomizeOrder; // 随机排序 + randomSeed = selector->randomSeed->getValueAt(frame); // 随机植入 - if (randomizeOrder) { - // 随机排序开启时,生成随机序号 - calculateRandomIndexs(randomSeed); - } + if (randomizeOrder) { + // 随机排序开启时,生成随机序号 + calculateRandomIndexs(randomSeed); + } } static float CalculateFactorSquare(float textStart, float textEnd, float rangeStart, float rangeEnd) { - // - // 正方形 - // ___________ - // | | - // | | - // | | - // __________| |__________ - // - if (textStart >= rangeEnd || textEnd <= rangeStart) { - return 0.0f; - } - auto textRange = textEnd - textStart; - if (textStart < rangeStart) { - textStart = rangeStart; - } - if (textEnd > rangeEnd) { - textEnd = rangeEnd; - } - auto factor = (textEnd - textStart) / textRange; - return factor; + // + // 正方形 + // ___________ + // | | + // | | + // | | + // __________| |__________ + // + if (textStart >= rangeEnd || textEnd <= rangeStart) { + return 0.0f; + } + auto textRange = textEnd - textStart; + if (textStart < rangeStart) { + textStart = rangeStart; + } + if (textEnd > rangeEnd) { + textEnd = rangeEnd; + } + auto factor = (textEnd - textStart) / textRange; + return factor; } static float CalculateRangeFactorRampUp(float textStart, float textEnd, float rangeStart, float rangeEnd) { - // - // 上斜坡 - // __________ - // / - // / - // / - // / - // / - // ___________/ - // - auto textCenter = (textStart + textEnd) * 0.5f; - auto factor = (textCenter - rangeStart) / (rangeEnd - rangeStart); - return factor; + // + // 上斜坡 + // __________ + // / + // / + // / + // / + // / + // ___________/ + // + auto textCenter = (textStart + textEnd) * 0.5f; + auto factor = (textCenter - rangeStart) / (rangeEnd - rangeStart); + return factor; } static float CalculateRangeFactorRampDown(float textStart, float textEnd, float rangeStart, - float rangeEnd) { - // - // 下斜坡 - // ___________ - // \ - // \ - // \ - // \ - // \ - // \_________ - // - auto textCenter = (textStart + textEnd) * 0.5f; - auto factor = (rangeEnd - textCenter) / (rangeEnd - rangeStart); - return factor; + float rangeEnd) { + // + // 下斜坡 + // ___________ + // \ + // \ + // \ + // \ + // \ + // \_________ + // + auto textCenter = (textStart + textEnd) * 0.5f; + auto factor = (rangeEnd - textCenter) / (rangeEnd - rangeStart); + return factor; } static float CalculateRangeFactorTriangle(float textStart, float textEnd, float rangeStart, - float rangeEnd) { - // - // 三角形 - // /\ - // / \ - // / \ - // / \ - // / \ - // __________/ \__________ - // - auto textCenter = (textStart + textEnd) * 0.5f; - auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; - float factor; - if (textCenter < rangeCenter) { - factor = (textCenter - rangeStart) / (rangeCenter - rangeStart); - } else { - factor = (rangeEnd - textCenter) / (rangeEnd - rangeCenter); - } - return factor; + float rangeEnd) { + // + // 三角形 + // /\ + // / \ + // / \ + // / \ + // / \ + // __________/ \__________ + // + auto textCenter = (textStart + textEnd) * 0.5f; + auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; + float factor; + if (textCenter < rangeCenter) { + factor = (textCenter - rangeStart) / (rangeCenter - rangeStart); + } else { + factor = (rangeEnd - textCenter) / (rangeEnd - rangeCenter); + } + return factor; } static float CalculateRangeFactorRound(float textStart, float textEnd, float rangeStart, float rangeEnd) { - // - // 圆形: - // 利用勾股定理确定高度:B*B = C*C - A*A (其中 C 为圆的半径) - // - // *** - // * * - // * /| * - // * / | * - // * / | * - // * C / | B * - // * / | * - // * / | * - // *_______________________/______|_________________* - // A - // - auto textCenter = (textStart + textEnd) * 0.5f; - if (textCenter >= rangeEnd || textCenter <= rangeStart) { - return 0.0f; - } - auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; - auto radius = (rangeEnd - rangeStart) * 0.5f; // C = radius - auto xWidth = rangeCenter - textCenter; // A = xWidth - auto yHeight = std::sqrt(radius * radius - xWidth * xWidth); // B = yHeight - auto factor = yHeight / radius; - return factor; + // + // 圆形: + // 利用勾股定理确定高度:B*B = C*C - A*A (其中 C 为圆的半径) + // + // *** + // * * + // * /| * + // * / | * + // * / | * + // * C / | B * + // * / | * + // * / | * + // *_______________________/______|_________________* + // A + // + auto textCenter = (textStart + textEnd) * 0.5f; + if (textCenter >= rangeEnd || textCenter <= rangeStart) { + return 0.0f; + } + auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; + auto radius = (rangeEnd - rangeStart) * 0.5f; // C = radius + auto xWidth = rangeCenter - textCenter; // A = xWidth + auto yHeight = std::sqrt(radius * radius - xWidth * xWidth); // B = yHeight + auto factor = yHeight / radius; + return factor; } static float CalculateRangeFactorSmooth(float textStart, float textEnd, float rangeStart, float rangeEnd) { - // - // 平滑 - // 三次贝塞尔曲线 - // _ - - - _ - // - - - // - - - // - - - // _ _ - // _ _ _ _ - - _ _ _ _ - // - auto textCenter = (textStart + textEnd) * 0.5f; - if (textCenter >= rangeEnd || textCenter <= rangeStart) { - return 0.0f; - } - auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; - float x = 0.0f; - if (textCenter < rangeCenter) { - x = (textCenter - rangeStart) / (rangeCenter - rangeStart); - } else { - x = (rangeEnd - textCenter) / (rangeEnd - rangeCenter); - } + // + // 平滑 + // 三次贝塞尔曲线 + // _ - - - _ + // - - + // - - + // - - + // _ _ + // _ _ _ _ - - _ _ _ _ + // + auto textCenter = (textStart + textEnd) * 0.5f; + if (textCenter >= rangeEnd || textCenter <= rangeStart) { + return 0.0f; + } + auto rangeCenter = (rangeStart + rangeEnd) * 0.5f; + float x = 0.0f; + if (textCenter < rangeCenter) { + x = (textCenter - rangeStart) / (rangeCenter - rangeStart); + } else { + x = (rangeEnd - textCenter) / (rangeEnd - rangeCenter); + } - // 根据AE实际数据, 拟合出贝塞尔曲线两个控制点 - // P1、P2的取值分别为(0.5, 0.0)、(0.5, 1.0) - static BezierEasing bezier = BezierEasing(Point::Make(0.5, 0.0), Point::Make(0.5, 1.0)); - auto factor = bezier.getInterpolation(x); - return factor; + // 根据AE实际数据, 拟合出贝塞尔曲线两个控制点 + // P1、P2的取值分别为(0.5, 0.0)、(0.5, 1.0) + static BezierEasing bezier = BezierEasing(Point::Make(0.5, 0.0), Point::Make(0.5, 1.0)); + auto factor = bezier.getInterpolation(x); + return factor; } void RangeSelectorRenderer::calculateBiasFlag(bool* pBiasFlag) { - if (pBiasFlag != nullptr) { - if (shape == TextRangeSelectorShape::Round || shape == TextRangeSelectorShape::Smooth) { - *pBiasFlag = true; // 圆形和平滑计算有误差 - } else if (randomizeOrder && randomSeed != 0 && textCount > 1) { - *pBiasFlag = true; // 随机数不为0时有误差 - } else { - *pBiasFlag = false; + if (pBiasFlag != nullptr) { + if (shape == TextRangeSelectorShape::Round || shape == TextRangeSelectorShape::Smooth) { + *pBiasFlag = true; // 圆形和平滑计算有误差 + } else if (randomizeOrder && randomSeed != 0 && textCount > 1) { + *pBiasFlag = true; // 随机数不为0时有误差 + } else { + *pBiasFlag = false; + } } - } } // 计算某个字符的范围因子 float RangeSelectorRenderer::calculateFactorByIndex(size_t index, bool* pBiasFlag) { - if (textCount == 0) { - return 0.0f; - } - if (randomizeOrder) { - index = randomIndexs[index]; // 从随机过后的列表中获取新的序号。 - } - auto textStart = static_cast(index) / textCount; - auto textEnd = static_cast(index + 1) / textCount; - auto factor = 0.0f; - switch (shape) { + if (textCount == 0) { + return 0.0f; + } + if (randomizeOrder) { + index = randomIndexs[index]; // 从随机过后的列表中获取新的序号。 + } + auto textStart = static_cast(index) / textCount; + auto textEnd = static_cast(index + 1) / textCount; + auto factor = 0.0f; + switch (shape) { case TextRangeSelectorShape::RampUp: // 上斜坡 - factor = CalculateRangeFactorRampUp(textStart, textEnd, rangeStart, rangeEnd); - break; + factor = CalculateRangeFactorRampUp(textStart, textEnd, rangeStart, rangeEnd); + break; case TextRangeSelectorShape::RampDown: // 下斜坡 - factor = CalculateRangeFactorRampDown(textStart, textEnd, rangeStart, rangeEnd); - break; + factor = CalculateRangeFactorRampDown(textStart, textEnd, rangeStart, rangeEnd); + break; case TextRangeSelectorShape::Triangle: // 三角形 - factor = CalculateRangeFactorTriangle(textStart, textEnd, rangeStart, rangeEnd); - break; + factor = CalculateRangeFactorTriangle(textStart, textEnd, rangeStart, rangeEnd); + break; case TextRangeSelectorShape::Round: // 圆形 - factor = CalculateRangeFactorRound(textStart, textEnd, rangeStart, rangeEnd); - break; + factor = CalculateRangeFactorRound(textStart, textEnd, rangeStart, rangeEnd); + break; case TextRangeSelectorShape::Smooth: // 平滑 - factor = CalculateRangeFactorSmooth(textStart, textEnd, rangeStart, rangeEnd); - break; + factor = CalculateRangeFactorSmooth(textStart, textEnd, rangeStart, rangeEnd); + break; default: // TextRangeSelectorShape::Square // 正方形 - factor = CalculateFactorSquare(textStart, textEnd, rangeStart, rangeEnd); - break; - } - if (factor < 0.0f) { - factor = 0.0f; - } else if (factor > 1.0f) { - factor = 1.0f; - } - factor *= amount; // 乘以高级选项里的"数量"系数 - calculateBiasFlag(pBiasFlag); - return factor; + factor = CalculateFactorSquare(textStart, textEnd, rangeStart, rangeEnd); + break; + } + if (factor < 0.0f) { + factor = 0.0f; + } else if (factor > 1.0f) { + factor = 1.0f; + } + factor *= amount; // 乘以高级选项里的"数量"系数 + calculateBiasFlag(pBiasFlag); + return factor; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/renderers/TextSelectorRenderer.h b/src/rendering/renderers/TextSelectorRenderer.h index 9646f99f62..114291a801 100644 --- a/src/rendering/renderers/TextSelectorRenderer.h +++ b/src/rendering/renderers/TextSelectorRenderer.h @@ -23,67 +23,67 @@ namespace pag { class TextSelectorRenderer { - public: - static float CalculateFactorFromSelectors( - const std::vector& selectorRenderers, size_t index, - bool* pBiasFlag = nullptr); - - TextSelectorRenderer(size_t textCount, Frame frame) : textCount(textCount), frame(frame) { - } - virtual ~TextSelectorRenderer() = default; - - // 叠加选择器 - float overlayFactor(float oldFactor, float factor, bool isFirstSelector); - - protected: - size_t textCount = 0; - Frame frame = 0; - Enum mode = TextSelectorMode::Intersect; // 模式 - std::vector randomIndexs; - - // 生成随机序号 - void calculateRandomIndexs(uint16_t seed); - // 计算某个字符的范围因子 - virtual float calculateFactorByIndex(size_t index, bool* pBiasFlag) = 0; +public: + static float CalculateFactorFromSelectors( + const std::vector& selectorRenderers, size_t index, + bool* pBiasFlag = nullptr); + + TextSelectorRenderer(size_t textCount, Frame frame) : textCount(textCount), frame(frame) { + } + virtual ~TextSelectorRenderer() = default; + + // 叠加选择器 + float overlayFactor(float oldFactor, float factor, bool isFirstSelector); + +protected: + size_t textCount = 0; + Frame frame = 0; + Enum mode = TextSelectorMode::Intersect; // 模式 + std::vector randomIndexs; + + // 生成随机序号 + void calculateRandomIndexs(uint16_t seed); + // 计算某个字符的范围因子 + virtual float calculateFactorByIndex(size_t index, bool* pBiasFlag) = 0; }; class WigglySelectorRenderer : public TextSelectorRenderer { - public: - WigglySelectorRenderer(const TextWigglySelector* selector, size_t textCount, Frame frame); - ~WigglySelectorRenderer() override = default; - - private: - // 计算某个字符的范围因子 - float calculateFactorByIndex(size_t index, bool* pBiasFlag) override; - - // 摆动选择器参数:模式(在父类里)、最大量、最小量、摆动/秒、关联、时间相位、空间相位 - float maxAmount = 1.0f; // 最大量 - float minAmount = 1.0f; // 最小量 - float wigglesPerSecond = 2.0f; - float correlation = 0.5f; // 关联 - float temporalPhase = 0; // 时间相位 - float spatialPhase = 0; // 空间相位 - uint16_t randomSeed = 0; // 随机植入 +public: + WigglySelectorRenderer(const TextWigglySelector* selector, size_t textCount, Frame frame); + ~WigglySelectorRenderer() override = default; + +private: + // 计算某个字符的范围因子 + float calculateFactorByIndex(size_t index, bool* pBiasFlag) override; + + // 摆动选择器参数:模式(在父类里)、最大量、最小量、摆动/秒、关联、时间相位、空间相位 + float maxAmount = 1.0f; // 最大量 + float minAmount = 1.0f; // 最小量 + float wigglesPerSecond = 2.0f; + float correlation = 0.5f; // 关联 + float temporalPhase = 0; // 时间相位 + float spatialPhase = 0; // 空间相位 + uint16_t randomSeed = 0; // 随机植入 }; class RangeSelectorRenderer : public TextSelectorRenderer { - public: - RangeSelectorRenderer(const TextRangeSelector* selector, size_t textCount, Frame frame); - ~RangeSelectorRenderer() override = default; - - private: - // 计算某个字符的范围因子 - float calculateFactorByIndex(size_t index, bool* pBiasFlag) override; - void calculateBiasFlag(bool* pBiasFlag); - - float rangeStart = 0.0f; - float rangeEnd = 1.0f; // AE默认范围是(0%-100%) - - // 范围选择器的高级选项:模式(在父类里)、数量、形状、随机排序 - float amount = 1.0f; // 数量 - Enum shape = TextRangeSelectorShape::Square; // 形状 - bool randomizeOrder = false; // 随机排序 - uint16_t randomSeed = 0; // 随机植入 +public: + RangeSelectorRenderer(const TextRangeSelector* selector, size_t textCount, Frame frame); + ~RangeSelectorRenderer() override = default; + +private: + // 计算某个字符的范围因子 + float calculateFactorByIndex(size_t index, bool* pBiasFlag) override; + void calculateBiasFlag(bool* pBiasFlag); + + float rangeStart = 0.0f; + float rangeEnd = 1.0f; // AE默认范围是(0%-100%) + + // 范围选择器的高级选项:模式(在父类里)、数量、形状、随机排序 + float amount = 1.0f; // 数量 + Enum shape = TextRangeSelectorShape::Square; // 形状 + bool randomizeOrder = false; // 随机排序 + uint16_t randomSeed = 0; // 随机植入 }; } // namespace pag diff --git a/src/rendering/renderers/TrackMatteRenderer.cpp b/src/rendering/renderers/TrackMatteRenderer.cpp index 0253c9ab4d..46f9f37796 100644 --- a/src/rendering/renderers/TrackMatteRenderer.cpp +++ b/src/rendering/renderers/TrackMatteRenderer.cpp @@ -24,92 +24,92 @@ namespace pag { static std::shared_ptr RenderColorGlyphs(TextLayer* layer, Frame layerFrame, - TextContent* textContent = nullptr, - Transform* extraTransform = nullptr) { - if (extraTransform && !extraTransform->visible()) { - return nullptr; - } - auto layerCache = LayerCache::Get(layer); - auto contentFrame = layerFrame - layer->startTime; - auto content = - textContent ? textContent : static_cast(layerCache->getContent(contentFrame)); - if (content->colorGlyphs == nullptr) { - return nullptr; - } - auto layerTransform = layerCache->getTransform(contentFrame); - Recorder recorder = {}; - recorder.saveLayer(layerTransform->opacity, layer->blendMode); - if (extraTransform) { - recorder.concat(extraTransform->matrix); - } - recorder.concat(layerTransform->matrix); - auto masks = layerCache->getMasks(contentFrame); - if (masks) { - recorder.saveClip(*masks); - } - recorder.drawGraphic(content->colorGlyphs); - if (masks) { + TextContent* textContent = nullptr, + Transform* extraTransform = nullptr) { + if (extraTransform && !extraTransform->visible()) { + return nullptr; + } + auto layerCache = LayerCache::Get(layer); + auto contentFrame = layerFrame - layer->startTime; + auto content = + textContent ? textContent : static_cast(layerCache->getContent(contentFrame)); + if (content->colorGlyphs == nullptr) { + return nullptr; + } + auto layerTransform = layerCache->getTransform(contentFrame); + Recorder recorder = {}; + recorder.saveLayer(layerTransform->opacity, layer->blendMode); + if (extraTransform) { + recorder.concat(extraTransform->matrix); + } + recorder.concat(layerTransform->matrix); + auto masks = layerCache->getMasks(contentFrame); + if (masks) { + recorder.saveClip(*masks); + } + recorder.drawGraphic(content->colorGlyphs); + if (masks) { + recorder.restore(); + } recorder.restore(); - } - recorder.restore(); - return recorder.makeGraphic(); + return recorder.makeGraphic(); } std::unique_ptr TrackMatteRenderer::Make(PAGLayer* trackMatteOwner) { - if (trackMatteOwner == nullptr || trackMatteOwner->_trackMatteLayer == nullptr) { - return nullptr; - } - auto trackMatteLayer = trackMatteOwner->_trackMatteLayer.get(); - auto trackMatteType = trackMatteOwner->layer->trackMatteType; - std::shared_ptr content = nullptr; - auto layerFrame = trackMatteLayer->contentFrame + trackMatteLayer->layer->startTime; - std::shared_ptr filterModifier = nullptr; - if (!trackMatteLayer->cacheFilters()) { - filterModifier = FilterModifier::Make(trackMatteLayer); - } - Recorder recorder = {}; - Transform extraTransform = {trackMatteLayer->layerMatrix, trackMatteLayer->layerOpacity}; - LayerRenderer::DrawLayer(&recorder, trackMatteLayer->layer, layerFrame, filterModifier, nullptr, - trackMatteLayer, &extraTransform); - content = recorder.makeGraphic(); + if (trackMatteOwner == nullptr || trackMatteOwner->_trackMatteLayer == nullptr) { + return nullptr; + } + auto trackMatteLayer = trackMatteOwner->_trackMatteLayer.get(); + auto trackMatteType = trackMatteOwner->layer->trackMatteType; + std::shared_ptr content = nullptr; + auto layerFrame = trackMatteLayer->contentFrame + trackMatteLayer->layer->startTime; + std::shared_ptr filterModifier = nullptr; + if (!trackMatteLayer->cacheFilters()) { + filterModifier = FilterModifier::Make(trackMatteLayer); + } + Recorder recorder = {}; + Transform extraTransform = {trackMatteLayer->layerMatrix, trackMatteLayer->layerOpacity}; + LayerRenderer::DrawLayer(&recorder, trackMatteLayer->layer, layerFrame, filterModifier, nullptr, + trackMatteLayer, &extraTransform); + content = recorder.makeGraphic(); - auto inverted = (trackMatteType == TrackMatteType::AlphaInverted || - trackMatteType == TrackMatteType::LumaInverted); - auto trackMatte = std::unique_ptr(new TrackMatte()); - trackMatte->modifier = Modifier::MakeMask(content, inverted); - if (trackMatte->modifier == nullptr) { - return nullptr; - } - if (trackMatteLayer->layerType() == LayerType::Text) { - auto textContent = static_cast(trackMatteLayer->getContent()); - trackMatte->colorGlyphs = RenderColorGlyphs(static_cast(trackMatteLayer->layer), - layerFrame, textContent, &extraTransform); - } - return trackMatte; + auto inverted = (trackMatteType == TrackMatteType::AlphaInverted || + trackMatteType == TrackMatteType::LumaInverted); + auto trackMatte = std::unique_ptr(new TrackMatte()); + trackMatte->modifier = Modifier::MakeMask(content, inverted); + if (trackMatte->modifier == nullptr) { + return nullptr; + } + if (trackMatteLayer->layerType() == LayerType::Text) { + auto textContent = static_cast(trackMatteLayer->getContent()); + trackMatte->colorGlyphs = RenderColorGlyphs(static_cast(trackMatteLayer->layer), + layerFrame, textContent, &extraTransform); + } + return trackMatte; } std::unique_ptr TrackMatteRenderer::Make(Layer* trackMatteOwner, Frame layerFrame) { - if (trackMatteOwner == nullptr || trackMatteOwner->trackMatteLayer == nullptr) { - return nullptr; - } - auto trackMatteLayer = trackMatteOwner->trackMatteLayer; - auto trackMatteType = trackMatteOwner->trackMatteType; - std::shared_ptr content = nullptr; - auto filterModifier = FilterModifier::Make(trackMatteLayer, layerFrame); - Recorder recorder = {}; - LayerRenderer::DrawLayer(&recorder, trackMatteLayer, layerFrame, filterModifier, nullptr); - content = recorder.makeGraphic(); - auto inverted = (trackMatteType == TrackMatteType::AlphaInverted || - trackMatteType == TrackMatteType::LumaInverted); - auto trackMatte = std::unique_ptr(new TrackMatte()); - trackMatte->modifier = Modifier::MakeMask(content, inverted); - if (trackMatte->modifier == nullptr) { - return nullptr; - } - if (trackMatteLayer->type() == LayerType::Text) { - trackMatte->colorGlyphs = - RenderColorGlyphs(static_cast(trackMatteLayer), layerFrame); - } - return trackMatte; + if (trackMatteOwner == nullptr || trackMatteOwner->trackMatteLayer == nullptr) { + return nullptr; + } + auto trackMatteLayer = trackMatteOwner->trackMatteLayer; + auto trackMatteType = trackMatteOwner->trackMatteType; + std::shared_ptr content = nullptr; + auto filterModifier = FilterModifier::Make(trackMatteLayer, layerFrame); + Recorder recorder = {}; + LayerRenderer::DrawLayer(&recorder, trackMatteLayer, layerFrame, filterModifier, nullptr); + content = recorder.makeGraphic(); + auto inverted = (trackMatteType == TrackMatteType::AlphaInverted || + trackMatteType == TrackMatteType::LumaInverted); + auto trackMatte = std::unique_ptr(new TrackMatte()); + trackMatte->modifier = Modifier::MakeMask(content, inverted); + if (trackMatte->modifier == nullptr) { + return nullptr; + } + if (trackMatteLayer->type() == LayerType::Text) { + trackMatte->colorGlyphs = + RenderColorGlyphs(static_cast(trackMatteLayer), layerFrame); + } + return trackMatte; } } // namespace pag diff --git a/src/rendering/renderers/TrackMatteRenderer.h b/src/rendering/renderers/TrackMatteRenderer.h index 2ca0b3d7e0..35774e4b0a 100644 --- a/src/rendering/renderers/TrackMatteRenderer.h +++ b/src/rendering/renderers/TrackMatteRenderer.h @@ -24,20 +24,20 @@ namespace pag { struct TrackMatte { - std::shared_ptr modifier = nullptr; - std::shared_ptr colorGlyphs = nullptr; + std::shared_ptr modifier = nullptr; + std::shared_ptr colorGlyphs = nullptr; }; class TrackMatteRenderer { - public: - /** - * Returns nullptr if trackMatteLayer is nullptr. - */ - static std::unique_ptr Make(PAGLayer* trackMatteOwner); +public: + /** + * Returns nullptr if trackMatteLayer is nullptr. + */ + static std::unique_ptr Make(PAGLayer* trackMatteOwner); - /** - * Returns nullptr if trackMatteLayer is nullptr. - */ - static std::unique_ptr Make(Layer* trackMatteOwner, Frame layerFrame); + /** + * Returns nullptr if trackMatteLayer is nullptr. + */ + static std::unique_ptr Make(Layer* trackMatteOwner, Frame layerFrame); }; } // namespace pag diff --git a/src/rendering/renderers/TransformRenderer.cpp b/src/rendering/renderers/TransformRenderer.cpp index b63798dc4b..7c688e004a 100644 --- a/src/rendering/renderers/TransformRenderer.cpp +++ b/src/rendering/renderers/TransformRenderer.cpp @@ -20,21 +20,21 @@ namespace pag { void RenderTransform(Transform* transform, Transform2D* transform2D, Frame layerFrame) { - auto& matrix = transform->matrix; - auto anchorPoint = transform2D->anchorPoint->getValueAt(layerFrame); - auto scale = transform2D->scale->getValueAt(layerFrame); - Point position = {}; - if (transform2D->position != nullptr) { - position = transform2D->position->getValueAt(layerFrame); - } else { - position.x = transform2D->xPosition->getValueAt(layerFrame); - position.y = transform2D->yPosition->getValueAt(layerFrame); - } - auto rotation = transform2D->rotation->getValueAt(layerFrame); - transform->opacity = transform2D->opacity->getValueAt(layerFrame); - matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); - matrix.postScale(scale.x, scale.y); - matrix.postRotate(rotation); - matrix.postTranslate(position.x, position.y); + auto& matrix = transform->matrix; + auto anchorPoint = transform2D->anchorPoint->getValueAt(layerFrame); + auto scale = transform2D->scale->getValueAt(layerFrame); + Point position = {}; + if (transform2D->position != nullptr) { + position = transform2D->position->getValueAt(layerFrame); + } else { + position.x = transform2D->xPosition->getValueAt(layerFrame); + position.y = transform2D->yPosition->getValueAt(layerFrame); + } + auto rotation = transform2D->rotation->getValueAt(layerFrame); + transform->opacity = transform2D->opacity->getValueAt(layerFrame); + matrix.postTranslate(-anchorPoint.x, -anchorPoint.y); + matrix.postScale(scale.x, scale.y); + matrix.postRotate(rotation); + matrix.postTranslate(position.x, position.y); } } // namespace pag diff --git a/src/rendering/utils/ApplyScaleMode.cpp b/src/rendering/utils/ApplyScaleMode.cpp index 045f1a4913..de233c5db9 100644 --- a/src/rendering/utils/ApplyScaleMode.cpp +++ b/src/rendering/utils/ApplyScaleMode.cpp @@ -21,37 +21,40 @@ namespace pag { Matrix ApplyScaleMode(int scaleMode, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) { - Matrix matrix = {}; - matrix.setIdentity(); - if (scaleMode == PAGScaleMode::None || sourceWidth <= 0 || sourceHeight <= 0 || - targetWidth <= 0 || targetHeight <= 0) { - return matrix; - } - auto scaleX = targetWidth * 1.0 / sourceWidth; - auto scaleY = targetHeight * 1.0 / sourceHeight; - switch (scaleMode) { + Matrix matrix = {}; + matrix.setIdentity(); + if (scaleMode == PAGScaleMode::None || sourceWidth <= 0 || sourceHeight <= 0 || + targetWidth <= 0 || targetHeight <= 0) { + return matrix; + } + auto scaleX = targetWidth * 1.0 / sourceWidth; + auto scaleY = targetHeight * 1.0 / sourceHeight; + switch (scaleMode) { case PAGScaleMode::Stretch: { - matrix.setScale(scaleX, scaleY); - } break; + matrix.setScale(scaleX, scaleY); + } + break; case PAGScaleMode::Zoom: { - auto scale = std::max(scaleX, scaleY); - matrix.setScale(scale, scale); - if (scaleX > scaleY) { - matrix.postTranslate(0, (targetHeight - sourceHeight * scale) * 0.5f); - } else { - matrix.postTranslate((targetWidth - sourceWidth * scale) * 0.5f, 0); - } - } break; + auto scale = std::max(scaleX, scaleY); + matrix.setScale(scale, scale); + if (scaleX > scaleY) { + matrix.postTranslate(0, (targetHeight - sourceHeight * scale) * 0.5f); + } else { + matrix.postTranslate((targetWidth - sourceWidth * scale) * 0.5f, 0); + } + } + break; default: { - auto scale = std::min(scaleX, scaleY); - matrix.setScale(scale, scale); - if (scaleX < scaleY) { - matrix.postTranslate(0, (targetHeight - sourceHeight * scale) * 0.5f); - } else { - matrix.postTranslate((targetWidth - sourceWidth * scale) * 0.5f, 0); - } - } break; - } - return matrix; + auto scale = std::min(scaleX, scaleY); + matrix.setScale(scale, scale); + if (scaleX < scaleY) { + matrix.postTranslate(0, (targetHeight - sourceHeight * scale) * 0.5f); + } else { + matrix.postTranslate((targetWidth - sourceWidth * scale) * 0.5f, 0); + } + } + break; + } + return matrix; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/utils/LockGuard.h b/src/rendering/utils/LockGuard.h index 48d49b423e..f310d6248c 100644 --- a/src/rendering/utils/LockGuard.h +++ b/src/rendering/utils/LockGuard.h @@ -24,21 +24,21 @@ namespace pag { class LockGuard { - public: - explicit LockGuard(std::shared_ptr locker) : mutex(std::move(locker)) { - if (mutex) { - mutex->lock(); +public: + explicit LockGuard(std::shared_ptr locker) : mutex(std::move(locker)) { + if (mutex) { + mutex->lock(); + } } - } - ~LockGuard() { - if (mutex) { - mutex->unlock(); + ~LockGuard() { + if (mutex) { + mutex->unlock(); + } } - } - private: - std::shared_ptr mutex; +private: + std::shared_ptr mutex; }; } // namespace pag diff --git a/src/rendering/utils/MemoryCalculator.cpp b/src/rendering/utils/MemoryCalculator.cpp index 6d7ae838f3..9bca55ffb9 100644 --- a/src/rendering/utils/MemoryCalculator.cpp +++ b/src/rendering/utils/MemoryCalculator.cpp @@ -21,312 +21,313 @@ namespace pag { static void* GetCacheResourcesForLayer(Layer* layer) { - switch (layer->type()) { + switch (layer->type()) { case LayerType::PreCompose: - return static_cast(layer)->composition; + return static_cast(layer)->composition; case LayerType::Image: - return static_cast(layer)->imageBytes; + return static_cast(layer)->imageBytes; default: - return layer; - } + return layer; + } } void MemoryCalculator::FillLayerGraphicsMemoriesPreFrame( Layer* layer, std::unordered_map& resourcesScaleMap, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, std::unordered_set& cachedResources) { - auto resources = GetCacheResourcesForLayer(layer); - if (cachedResources.find(resources) != cachedResources.end()) { - return; - } - if (!layer->isActive) { - return; - } - cachedResources.insert(resources); + auto resources = GetCacheResourcesForLayer(layer); + if (cachedResources.find(resources) != cachedResources.end()) { + return; + } + if (!layer->isActive) { + return; + } + cachedResources.insert(resources); - auto layerType = layer->type(); - switch (layerType) { + auto layerType = layer->type(); + switch (layerType) { case LayerType::PreCompose: - FillCompositionGraphicsMemories(static_cast(layer)->composition, - resourcesScaleMap, resourcesTimeRangesMap, memoriesPreFrame, - cachedResources); - break; - default: { - auto layerCache = LayerCache::Get(layer); - if (!layerCache->cacheEnabled()) { - break; - } - auto scaleIter = resourcesScaleMap.find(resources); - if (scaleIter == resourcesScaleMap.end()) { - LOGE("layer's scale has not calculated"); + FillCompositionGraphicsMemories(static_cast(layer)->composition, + resourcesScaleMap, resourcesTimeRangesMap, memoriesPreFrame, + cachedResources); break; - } - auto layerContent = layerCache->getContent(0); - Rect bounds = {}; - layerContent->measureBounds(&bounds); - auto scale = std::max(scaleIter->second.x, scaleIter->second.y); - if (layerType == LayerType::Image) { - scale = std::min(scale, 1.0f); - } - bounds.setWH(ceil(bounds.width() * scale), ceil(bounds.height() * scale)); - int64_t graphicsMemory = ceil(bounds.width()) * ceil(bounds.height()) * 4; // w*h*scale*rgba - auto timeRanges = resourcesTimeRangesMap.find(resources)->second; - for (auto& timeRange : *timeRanges) { - for (Frame frame = timeRange.start; frame <= timeRange.end; frame++) { - if (static_cast(frame) >= memoriesPreFrame.size()) { + default: { + auto layerCache = LayerCache::Get(layer); + if (!layerCache->cacheEnabled()) { + break; + } + auto scaleIter = resourcesScaleMap.find(resources); + if (scaleIter == resourcesScaleMap.end()) { + LOGE("layer's scale has not calculated"); break; - } - memoriesPreFrame[frame] += graphicsMemory; } - } - } break; - } + auto layerContent = layerCache->getContent(0); + Rect bounds = {}; + layerContent->measureBounds(&bounds); + auto scale = std::max(scaleIter->second.x, scaleIter->second.y); + if (layerType == LayerType::Image) { + scale = std::min(scale, 1.0f); + } + bounds.setWH(ceil(bounds.width() * scale), ceil(bounds.height() * scale)); + int64_t graphicsMemory = ceil(bounds.width()) * ceil(bounds.height()) * 4; // w*h*scale*rgba + auto timeRanges = resourcesTimeRangesMap.find(resources)->second; + for (auto& timeRange : *timeRanges) { + for (Frame frame = timeRange.start; frame <= timeRange.end; frame++) { + if (static_cast(frame) >= memoriesPreFrame.size()) { + break; + } + memoriesPreFrame[frame] += graphicsMemory; + } + } + } + break; + } } void FillGraphicsMemories( Composition* composition, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, int64_t& graphicsMemory) { - // Just use the last one for best rendering quality, ignore all others. - auto timeRanges = resourcesTimeRangesMap.find(composition)->second; - for (auto timeRangeIter = timeRanges->begin(); timeRangeIter != timeRanges->end(); - timeRangeIter++) { - auto timeRange = *timeRangeIter; - for (auto frame = timeRange.start; frame <= timeRange.end; frame++) { - if (static_cast(frame) < memoriesPreFrame.size()) { - std::vector::size_type currentFrame = (std::vector::size_type)frame; - memoriesPreFrame[currentFrame] += graphicsMemory; - } else { - break; - } + // Just use the last one for best rendering quality, ignore all others. + auto timeRanges = resourcesTimeRangesMap.find(composition)->second; + for (auto timeRangeIter = timeRanges->begin(); timeRangeIter != timeRanges->end(); + timeRangeIter++) { + auto timeRange = *timeRangeIter; + for (auto frame = timeRange.start; frame <= timeRange.end; frame++) { + if (static_cast(frame) < memoriesPreFrame.size()) { + std::vector::size_type currentFrame = (std::vector::size_type)frame; + memoriesPreFrame[currentFrame] += graphicsMemory; + } else { + break; + } + } } - } } void MemoryCalculator::FillBitmapGraphicsMemories( Composition* composition, std::unordered_map&, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, int64_t& graphicsMemory) { - // Just use the last one for best rendering quality, ignore all others. - auto sequence = static_cast(composition)->sequences.back(); - graphicsMemory += sequence->width * sequence->height * 4; - FillGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, graphicsMemory); + // Just use the last one for best rendering quality, ignore all others. + auto sequence = static_cast(composition)->sequences.back(); + graphicsMemory += sequence->width * sequence->height * 4; + FillGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, graphicsMemory); } void MemoryCalculator::FillVideoGraphicsMemories( Composition* composition, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, int64_t& graphicsMemory) { - // Just use the last one for best rendering quality, ignore all others. - auto sequence = static_cast(composition)->sequences.back(); - auto factor = sequence->alphaStartX > 0 || sequence->alphaStartY > 0 ? 3 : 2; - graphicsMemory += sequence->width * sequence->height * 4 * factor; - FillGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, graphicsMemory); + // Just use the last one for best rendering quality, ignore all others. + auto sequence = static_cast(composition)->sequences.back(); + auto factor = sequence->alphaStartX > 0 || sequence->alphaStartY > 0 ? 3 : 2; + graphicsMemory += sequence->width * sequence->height * 4 * factor; + FillGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, graphicsMemory); } void MemoryCalculator::FillVectorGraphicsMemories( Composition* composition, std::unordered_map& resourcesScaleMap, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, std::unordered_set& cachedResources) { - VectorComposition* vectorComposition = static_cast(composition); - for (auto iter = vectorComposition->layers.begin(); iter != vectorComposition->layers.end(); - iter++) { - auto layer = *iter; - FillLayerGraphicsMemoriesPreFrame(layer, resourcesScaleMap, resourcesTimeRangesMap, - memoriesPreFrame, cachedResources); - } + VectorComposition* vectorComposition = static_cast(composition); + for (auto iter = vectorComposition->layers.begin(); iter != vectorComposition->layers.end(); + iter++) { + auto layer = *iter; + FillLayerGraphicsMemoriesPreFrame(layer, resourcesScaleMap, resourcesTimeRangesMap, + memoriesPreFrame, cachedResources); + } } int64_t MemoryCalculator::FillCompositionGraphicsMemories( Composition* composition, std::unordered_map& resourcesScaleMap, std::unordered_map*>& resourcesTimeRangesMap, std::vector& memoriesPreFrame, std::unordered_set& cachedResources) { - int64_t graphicsMemory = 0; - switch (composition->type()) { + int64_t graphicsMemory = 0; + switch (composition->type()) { case CompositionType::Vector: { - FillVectorGraphicsMemories(composition, resourcesScaleMap, resourcesTimeRangesMap, - memoriesPreFrame, cachedResources); - break; + FillVectorGraphicsMemories(composition, resourcesScaleMap, resourcesTimeRangesMap, + memoriesPreFrame, cachedResources); + break; } case CompositionType::Bitmap: { - FillBitmapGraphicsMemories(composition, resourcesScaleMap, resourcesTimeRangesMap, - memoriesPreFrame, graphicsMemory); - break; + FillBitmapGraphicsMemories(composition, resourcesScaleMap, resourcesTimeRangesMap, + memoriesPreFrame, graphicsMemory); + break; } case CompositionType::Video: { - FillVideoGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, - graphicsMemory); - break; + FillVideoGraphicsMemories(composition, resourcesTimeRangesMap, memoriesPreFrame, + graphicsMemory); + break; } default: - break; - } - return graphicsMemory; + break; + } + return graphicsMemory; } std::vector MemoryCalculator::GetRootLayerGraphicsMemoriesPreFrame( PreComposeLayer* rootLayer, std::unordered_map& resourcesScaleMap, std::unordered_map*>& resourcesTimeRangesMap) { - std::unordered_set cachedResources; - if (static_cast(rootLayer->composition->duration) > std::vector().max_size()) { - return std::vector(); - } - auto duration = (std::vector::size_type)rootLayer->composition->duration; - std::vector memoriesPreFrame(duration, 0); - FillLayerGraphicsMemoriesPreFrame(rootLayer, resourcesScaleMap, resourcesTimeRangesMap, - memoriesPreFrame, cachedResources); - return memoriesPreFrame; + std::unordered_set cachedResources; + if (static_cast(rootLayer->composition->duration) > std::vector().max_size()) { + return std::vector(); + } + auto duration = (std::vector::size_type)rootLayer->composition->duration; + std::vector memoriesPreFrame(duration, 0); + FillLayerGraphicsMemoriesPreFrame(rootLayer, resourcesScaleMap, resourcesTimeRangesMap, + memoriesPreFrame, cachedResources); + return memoriesPreFrame; } bool MemoryCalculator::UpdateMaxScaleMapIfNeed( void* resource, Point currentScale, std::unordered_map& resourcesMaxScaleMap) { - auto maxScale = currentScale; - auto iter = resourcesMaxScaleMap.find(resource); - bool hasChange = true; - if (iter != resourcesMaxScaleMap.end()) { - auto scale = iter->second; - hasChange = maxScale.x > scale.x || maxScale.y > scale.y; - maxScale.x = maxScale.x > scale.x ? maxScale.x : scale.x; - maxScale.y = maxScale.y > scale.y ? maxScale.y : scale.y; + auto maxScale = currentScale; + auto iter = resourcesMaxScaleMap.find(resource); + bool hasChange = true; + if (iter != resourcesMaxScaleMap.end()) { + auto scale = iter->second; + hasChange = maxScale.x > scale.x || maxScale.y > scale.y; + maxScale.x = maxScale.x > scale.x ? maxScale.x : scale.x; + maxScale.y = maxScale.y > scale.y ? maxScale.y : scale.y; + if (hasChange) { + resourcesMaxScaleMap.erase(iter); + } + } if (hasChange) { - resourcesMaxScaleMap.erase(iter); + resourcesMaxScaleMap.insert(std::make_pair(resource, maxScale)); } - } - if (hasChange) { - resourcesMaxScaleMap.insert(std::make_pair(resource, maxScale)); - } - return hasChange; + return hasChange; } static bool TimeRangesHaveIntersection(const TimeRange& range, const TimeRange& otherRange) { - return (range.start >= otherRange.start && range.start <= otherRange.end) || - (otherRange.start >= range.start && otherRange.start <= range.end); + return (range.start >= otherRange.start && range.start <= otherRange.end) || + (otherRange.start >= range.start && otherRange.start <= range.end); } // Method will make mistake when ranges don't have intersection static TimeRange UnionTimeRanges(const TimeRange& range, const TimeRange& otherRange) { - TimeRange unionRange; - unionRange.start = range.start < otherRange.start ? range.start : otherRange.start; - unionRange.end = range.end > otherRange.end ? range.end : otherRange.end; - return unionRange; + TimeRange unionRange; + unionRange.start = range.start < otherRange.start ? range.start : otherRange.start; + unionRange.end = range.end > otherRange.end ? range.end : otherRange.end; + return unionRange; } void MemoryCalculator::UpdateTimeRangesMapIfNeed( void* resource, TimeRange timeRange, std::unordered_map*>& resourcesTimeRangesMap, bool needUnion) { - auto iter = resourcesTimeRangesMap.find(resource); - std::vector* resourceTimeRanges; - if (iter != resourcesTimeRangesMap.end()) { - resourceTimeRanges = iter->second; - } else { - resourceTimeRanges = new std::vector(); - resourcesTimeRangesMap.insert(std::make_pair(resource, resourceTimeRanges)); - } - auto timeRangeNeedAdd = timeRange; - if (needUnion) { - for (auto timeRangeIter = resourceTimeRanges->end() - 1; - timeRangeIter != resourceTimeRanges->begin() - 1; timeRangeIter--) { - if (TimeRangesHaveIntersection(*timeRangeIter, timeRangeNeedAdd)) { - timeRangeNeedAdd = UnionTimeRanges(*timeRangeIter, timeRangeNeedAdd); - resourceTimeRanges->erase(timeRangeIter); - } + auto iter = resourcesTimeRangesMap.find(resource); + std::vector* resourceTimeRanges; + if (iter != resourcesTimeRangesMap.end()) { + resourceTimeRanges = iter->second; + } else { + resourceTimeRanges = new std::vector(); + resourcesTimeRangesMap.insert(std::make_pair(resource, resourceTimeRanges)); + } + auto timeRangeNeedAdd = timeRange; + if (needUnion) { + for (auto timeRangeIter = resourceTimeRanges->end() - 1; + timeRangeIter != resourceTimeRanges->begin() - 1; timeRangeIter--) { + if (TimeRangesHaveIntersection(*timeRangeIter, timeRangeNeedAdd)) { + timeRangeNeedAdd = UnionTimeRanges(*timeRangeIter, timeRangeNeedAdd); + resourceTimeRanges->erase(timeRangeIter); + } + } } - } - resourceTimeRanges->push_back(timeRangeNeedAdd); + resourceTimeRanges->push_back(timeRangeNeedAdd); } void MemoryCalculator::UpdateTimeRange( Layer* layer, Frame referenceStartTime, std::unordered_map*>& resourcesTimeRangesMap) { - if (!layer->isActive) { - return; - } - TimeRange timeRange; - timeRange.start = referenceStartTime + layer->startTime; - timeRange.end = timeRange.start + layer->duration - 1; - bool needUnionTimeRange = true; - if (layer->type() == LayerType::PreCompose) { - auto composition = static_cast(layer)->composition; - if (composition->type() == CompositionType::Vector) { - auto sublayers = static_cast(composition)->layers; - for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { - UpdateTimeRange(*iter, timeRange.start, resourcesTimeRangesMap); - } + if (!layer->isActive) { + return; } - } - UpdateTimeRangesMapIfNeed(GetCacheResourcesForLayer(layer), timeRange, resourcesTimeRangesMap, - needUnionTimeRange); + TimeRange timeRange; + timeRange.start = referenceStartTime + layer->startTime; + timeRange.end = timeRange.start + layer->duration - 1; + bool needUnionTimeRange = true; + if (layer->type() == LayerType::PreCompose) { + auto composition = static_cast(layer)->composition; + if (composition->type() == CompositionType::Vector) { + auto sublayers = static_cast(composition)->layers; + for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { + UpdateTimeRange(*iter, timeRange.start, resourcesTimeRangesMap); + } + } + } + UpdateTimeRangesMapIfNeed(GetCacheResourcesForLayer(layer), timeRange, resourcesTimeRangesMap, + needUnionTimeRange); } void MemoryCalculator::UpdateMaxScaleAndTimeRange( Layer* layer, Point referenceScale, Frame referenceStartTime, std::unordered_map& resourcesMaxScaleMap, std::unordered_map*>& resourcesTimeRangesMap) { - if (!layer->isActive) { - return; - } - TimeRange timeRange; - timeRange.start = referenceStartTime + layer->startTime; - timeRange.end = timeRange.start + layer->duration - 1; - bool needUnionTimeRange = true; - if (layer->type() == LayerType::PreCompose) { - auto composition = static_cast(layer)->composition; - auto layerScale = layer->getMaxScaleFactor(); - bool maxScaleHasChage = UpdateMaxScaleMapIfNeed( - composition, {referenceScale.x * layerScale.x, referenceScale.y * layerScale.y}, - resourcesMaxScaleMap); - if (composition->type() == CompositionType::Vector) { - if (maxScaleHasChage) { - auto maxScale = resourcesMaxScaleMap.find(composition)->second; - auto sublayers = static_cast(composition)->layers; - for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { - UpdateMaxScaleAndTimeRange(*iter, maxScale, timeRange.start, resourcesMaxScaleMap, - resourcesTimeRangesMap); - } - } else { - auto sublayers = static_cast(composition)->layers; - for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { - UpdateTimeRange(*iter, timeRange.start, resourcesTimeRangesMap); + if (!layer->isActive) { + return; + } + TimeRange timeRange; + timeRange.start = referenceStartTime + layer->startTime; + timeRange.end = timeRange.start + layer->duration - 1; + bool needUnionTimeRange = true; + if (layer->type() == LayerType::PreCompose) { + auto composition = static_cast(layer)->composition; + auto layerScale = layer->getMaxScaleFactor(); + bool maxScaleHasChage = UpdateMaxScaleMapIfNeed( + composition, {referenceScale.x * layerScale.x, referenceScale.y * layerScale.y}, + resourcesMaxScaleMap); + if (composition->type() == CompositionType::Vector) { + if (maxScaleHasChage) { + auto maxScale = resourcesMaxScaleMap.find(composition)->second; + auto sublayers = static_cast(composition)->layers; + for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { + UpdateMaxScaleAndTimeRange(*iter, maxScale, timeRange.start, resourcesMaxScaleMap, + resourcesTimeRangesMap); + } + } else { + auto sublayers = static_cast(composition)->layers; + for (auto iter = sublayers.begin(); iter != sublayers.end(); iter++) { + UpdateTimeRange(*iter, timeRange.start, resourcesTimeRangesMap); + } + } } - } + } else { + auto cacheResources = GetCacheResourcesForLayer(layer); + auto layerScale = layer->getMaxScaleFactor(); + UpdateMaxScaleMapIfNeed(cacheResources, + {referenceScale.x * layerScale.x, referenceScale.y * layerScale.y}, + resourcesMaxScaleMap); } - } else { - auto cacheResources = GetCacheResourcesForLayer(layer); - auto layerScale = layer->getMaxScaleFactor(); - UpdateMaxScaleMapIfNeed(cacheResources, - {referenceScale.x * layerScale.x, referenceScale.y * layerScale.y}, - resourcesMaxScaleMap); - } - UpdateTimeRangesMapIfNeed(GetCacheResourcesForLayer(layer), timeRange, resourcesTimeRangesMap, - needUnionTimeRange); + UpdateTimeRangesMapIfNeed(GetCacheResourcesForLayer(layer), timeRange, resourcesTimeRangesMap, + needUnionTimeRange); } void MemoryCalculator::CaculateResourcesMaxScaleAndTimeRanges( Layer* rootLayer, std::unordered_map& resourcesMaxScaleMap, std::unordered_map*>& resourcesTimeRangesMap) { - UpdateMaxScaleAndTimeRange(rootLayer, {1, 1}, rootLayer->startTime, resourcesMaxScaleMap, - resourcesTimeRangesMap); + UpdateMaxScaleAndTimeRange(rootLayer, {1, 1}, rootLayer->startTime, resourcesMaxScaleMap, + resourcesTimeRangesMap); } int64_t CalculateGraphicsMemory(std::shared_ptr file) { - if (file == nullptr) { - return 0; - } - auto rootLayer = file->getRootLayer(); - std::unordered_map resourcesMaxScaleMap; - std::unordered_map*> resourcesTimeRangesMap; - MemoryCalculator::CaculateResourcesMaxScaleAndTimeRanges(rootLayer, resourcesMaxScaleMap, - resourcesTimeRangesMap); - std::vector memoriesPreFrame = MemoryCalculator::GetRootLayerGraphicsMemoriesPreFrame( - rootLayer, resourcesMaxScaleMap, resourcesTimeRangesMap); - int64_t maxGraphicsMemory = 0; - for (std::vector::size_type i = 0; i < memoriesPreFrame.size(); i++) { - maxGraphicsMemory = - maxGraphicsMemory > memoriesPreFrame[i] ? maxGraphicsMemory : memoriesPreFrame[i]; - } - for (auto it = resourcesTimeRangesMap.begin(); it != resourcesTimeRangesMap.end(); it++) { - delete it->second; - } - return maxGraphicsMemory; + if (file == nullptr) { + return 0; + } + auto rootLayer = file->getRootLayer(); + std::unordered_map resourcesMaxScaleMap; + std::unordered_map*> resourcesTimeRangesMap; + MemoryCalculator::CaculateResourcesMaxScaleAndTimeRanges(rootLayer, resourcesMaxScaleMap, + resourcesTimeRangesMap); + std::vector memoriesPreFrame = MemoryCalculator::GetRootLayerGraphicsMemoriesPreFrame( + rootLayer, resourcesMaxScaleMap, resourcesTimeRangesMap); + int64_t maxGraphicsMemory = 0; + for (std::vector::size_type i = 0; i < memoriesPreFrame.size(); i++) { + maxGraphicsMemory = + maxGraphicsMemory > memoriesPreFrame[i] ? maxGraphicsMemory : memoriesPreFrame[i]; + } + for (auto it = resourcesTimeRangesMap.begin(); it != resourcesTimeRangesMap.end(); it++) { + delete it->second; + } + return maxGraphicsMemory; } } // namespace pag diff --git a/src/rendering/utils/MemoryCalculator.h b/src/rendering/utils/MemoryCalculator.h index 0a8d690600..568148b19b 100644 --- a/src/rendering/utils/MemoryCalculator.h +++ b/src/rendering/utils/MemoryCalculator.h @@ -24,55 +24,55 @@ namespace pag { class MemoryCalculator { - public: - static void CaculateResourcesMaxScaleAndTimeRanges( - Layer* rootLayer, std::unordered_map& resourcesMaxScaleMap, - std::unordered_map*>& resourcesTimeRangesMap); +public: + static void CaculateResourcesMaxScaleAndTimeRanges( + Layer* rootLayer, std::unordered_map& resourcesMaxScaleMap, + std::unordered_map*>& resourcesTimeRangesMap); - static std::vector GetRootLayerGraphicsMemoriesPreFrame( - PreComposeLayer* rootLayer, std::unordered_map& resourcesScaleMap, - std::unordered_map*>& resourcesTimeRangesMap); + static std::vector GetRootLayerGraphicsMemoriesPreFrame( + PreComposeLayer* rootLayer, std::unordered_map& resourcesScaleMap, + std::unordered_map*>& resourcesTimeRangesMap); - private: - static void FillBitmapGraphicsMemories( - Composition* composition, std::unordered_map& resourcesScaleMap, - std::unordered_map*>& resourcesTimeRangesMap, - std::vector& memoriesPreFrame, int64_t& graphicsMemory); +private: + static void FillBitmapGraphicsMemories( + Composition* composition, std::unordered_map& resourcesScaleMap, + std::unordered_map*>& resourcesTimeRangesMap, + std::vector& memoriesPreFrame, int64_t& graphicsMemory); - static void FillVideoGraphicsMemories( - Composition* composition, - std::unordered_map*>& resourcesTimeRangesMap, - std::vector& memoriesPreFrame, int64_t& graphicsMemory); + static void FillVideoGraphicsMemories( + Composition* composition, + std::unordered_map*>& resourcesTimeRangesMap, + std::vector& memoriesPreFrame, int64_t& graphicsMemory); - static void FillVectorGraphicsMemories( - Composition* composition, std::unordered_map& resourcesScaleMap, - std::unordered_map*>& resourcesTimeRangesMap, - std::vector& memoriesPreFrame, std::unordered_set& cachedResources); + static void FillVectorGraphicsMemories( + Composition* composition, std::unordered_map& resourcesScaleMap, + std::unordered_map*>& resourcesTimeRangesMap, + std::vector& memoriesPreFrame, std::unordered_set& cachedResources); - static int64_t FillCompositionGraphicsMemories( - Composition* composition, std::unordered_map& resourcesScaleMap, - std::unordered_map*>& resourcesTimeRangesMap, - std::vector& memoriesPreFrame, std::unordered_set& cachedResources); + static int64_t FillCompositionGraphicsMemories( + Composition* composition, std::unordered_map& resourcesScaleMap, + std::unordered_map*>& resourcesTimeRangesMap, + std::vector& memoriesPreFrame, std::unordered_set& cachedResources); - static void FillLayerGraphicsMemoriesPreFrame( - Layer* layer, std::unordered_map& resourcesScaleMap, - std::unordered_map*>& resourcesTimeRangesMap, - std::vector& memoriesPreFrame, std::unordered_set& cachedResources); + static void FillLayerGraphicsMemoriesPreFrame( + Layer* layer, std::unordered_map& resourcesScaleMap, + std::unordered_map*>& resourcesTimeRangesMap, + std::vector& memoriesPreFrame, std::unordered_set& cachedResources); - static bool UpdateMaxScaleMapIfNeed(void* resource, Point currentScale, - std::unordered_map& resourcesMaxScaleMap); - static void UpdateTimeRangesMapIfNeed( - void* resource, TimeRange timeRange, - std::unordered_map*>& resourcesTimeRangesMap, - bool needUnion = true); + static bool UpdateMaxScaleMapIfNeed(void* resource, Point currentScale, + std::unordered_map& resourcesMaxScaleMap); + static void UpdateTimeRangesMapIfNeed( + void* resource, TimeRange timeRange, + std::unordered_map*>& resourcesTimeRangesMap, + bool needUnion = true); - static void UpdateTimeRange( - Layer* layer, Frame referenceStartTime, - std::unordered_map*>& resourcesTimeRangesMap); + static void UpdateTimeRange( + Layer* layer, Frame referenceStartTime, + std::unordered_map*>& resourcesTimeRangesMap); - static void UpdateMaxScaleAndTimeRange( - Layer* layer, Point referenceScale, Frame referenceStartTime, - std::unordered_map& resourcesMaxScaleMap, - std::unordered_map*>& resourcesTimeRangesMap); + static void UpdateMaxScaleAndTimeRange( + Layer* layer, Point referenceScale, Frame referenceStartTime, + std::unordered_map& resourcesMaxScaleMap, + std::unordered_map*>& resourcesTimeRangesMap); }; } // namespace pag diff --git a/src/rendering/utils/PathUtil.cpp b/src/rendering/utils/PathUtil.cpp index b3b1e6bd28..191fe256de 100644 --- a/src/rendering/utils/PathUtil.cpp +++ b/src/rendering/utils/PathUtil.cpp @@ -20,31 +20,31 @@ namespace pag { Path ToPath(const PathData& pathData) { - Path path = {}; - auto& points = pathData.points; - uint32_t index = 0; - Point control1 = {}, control2 = {}, point = {}; - for (auto& verb : pathData.verbs) { - switch (verb) { - case PathDataVerb::Close: - path.close(); - break; - case PathDataVerb::MoveTo: - point = points[index++]; - path.moveTo(point.x, point.y); - break; - case PathDataVerb::LineTo: - point = points[index++]; - path.lineTo(point.x, point.y); - break; - case PathDataVerb::CurveTo: - control1 = points[index++]; - control2 = points[index++]; - point = points[index++]; - path.cubicTo(control1.x, control1.y, control2.x, control2.y, point.x, point.y); - break; + Path path = {}; + auto& points = pathData.points; + uint32_t index = 0; + Point control1 = {}, control2 = {}, point = {}; + for (auto& verb : pathData.verbs) { + switch (verb) { + case PathDataVerb::Close: + path.close(); + break; + case PathDataVerb::MoveTo: + point = points[index++]; + path.moveTo(point.x, point.y); + break; + case PathDataVerb::LineTo: + point = points[index++]; + path.lineTo(point.x, point.y); + break; + case PathDataVerb::CurveTo: + control1 = points[index++]; + control2 = points[index++]; + point = points[index++]; + path.cubicTo(control1.x, control1.y, control2.x, control2.y, point.x, point.y); + break; + } } - } - return path; + return path; } } // namespace pag \ No newline at end of file diff --git a/src/rendering/utils/ScopedLock.cpp b/src/rendering/utils/ScopedLock.cpp index 1329cc0c2a..3ba8b36b0b 100644 --- a/src/rendering/utils/ScopedLock.cpp +++ b/src/rendering/utils/ScopedLock.cpp @@ -21,25 +21,25 @@ namespace pag { ScopedLock::ScopedLock(std::shared_ptr first, std::shared_ptr second) : firstLocker(std::move(first)), secondLocker(std::move(second)) { - if (firstLocker == nullptr) { - return; - } - if (firstLocker == secondLocker) { - secondLocker = nullptr; - } - if (secondLocker) { - std::lock(*firstLocker, *secondLocker); - } else { - firstLocker->lock(); - } + if (firstLocker == nullptr) { + return; + } + if (firstLocker == secondLocker) { + secondLocker = nullptr; + } + if (secondLocker) { + std::lock(*firstLocker, *secondLocker); + } else { + firstLocker->lock(); + } } ScopedLock::~ScopedLock() { - if (firstLocker) { - firstLocker->unlock(); - } - if (secondLocker) { - secondLocker->unlock(); - } + if (firstLocker) { + firstLocker->unlock(); + } + if (secondLocker) { + secondLocker->unlock(); + } } } // namespace pag \ No newline at end of file diff --git a/src/rendering/utils/ScopedLock.h b/src/rendering/utils/ScopedLock.h index 7a3d689ed3..c9c0e98e09 100644 --- a/src/rendering/utils/ScopedLock.h +++ b/src/rendering/utils/ScopedLock.h @@ -23,13 +23,13 @@ namespace pag { class ScopedLock { - public: - ScopedLock(std::shared_ptr first, std::shared_ptr second); +public: + ScopedLock(std::shared_ptr first, std::shared_ptr second); - ~ScopedLock(); + ~ScopedLock(); - private: - std::shared_ptr firstLocker = nullptr; - std::shared_ptr secondLocker = nullptr; +private: + std::shared_ptr firstLocker = nullptr; + std::shared_ptr secondLocker = nullptr; }; } // namespace pag diff --git a/src/rendering/utils/Transform.h b/src/rendering/utils/Transform.h index 74c64392bc..e87680a7dc 100644 --- a/src/rendering/utils/Transform.h +++ b/src/rendering/utils/Transform.h @@ -22,19 +22,19 @@ namespace pag { class Transform { - public: - Transform() { - matrix.setIdentity(); - } +public: + Transform() { + matrix.setIdentity(); + } - Transform(const Matrix& matrix, Opacity opacity) : matrix(matrix), opacity(opacity) { - } + Transform(const Matrix& matrix, Opacity opacity) : matrix(matrix), opacity(opacity) { + } - bool visible() const { - return matrix.invertible() && opacity > 0; - } + bool visible() const { + return matrix.invertible() && opacity > 0; + } - Matrix matrix = {}; - Opacity opacity = Opaque; + Matrix matrix = {}; + Opacity opacity = Opaque; }; } // namespace pag diff --git a/src/video/DecodingPolicy.h b/src/video/DecodingPolicy.h index 034ecad7ba..56e8c93542 100644 --- a/src/video/DecodingPolicy.h +++ b/src/video/DecodingPolicy.h @@ -20,18 +20,18 @@ namespace pag { enum class DecodingPolicy { - /** - * Uses hardware decoders. - */ - Hardware, - /** - * Uses software decoders. - */ - Software, - /** - * Uses a software decoder first, but initializes a hardware on async thread, and then switches to - * the hardware decoder when it is initialized. - */ - SoftwareToHardware + /** + * Uses hardware decoders. + */ + Hardware, + /** + * Uses software decoders. + */ + Software, + /** + * Uses a software decoder first, but initializes a hardware on async thread, and then switches to + * the hardware decoder when it is initialized. + */ + SoftwareToHardware }; } // namespace pag diff --git a/src/video/I420Buffer.cpp b/src/video/I420Buffer.cpp index e23c385e95..d6723c6851 100644 --- a/src/video/I420Buffer.cpp +++ b/src/video/I420Buffer.cpp @@ -24,21 +24,21 @@ namespace pag { I420Buffer::I420Buffer(int width, int height, uint8_t** data, const int* lineSize, YUVColorSpace colorSpace, YUVColorRange colorRange) : VideoBuffer(width, height), colorSpace(colorSpace), colorRange(colorRange) { - for (int i = 0; i < I420_PLANE_COUNT; i++) { - pixelsPlane[i] = data[i]; - rowBytesPlane[i] = lineSize[i]; - } + for (int i = 0; i < I420_PLANE_COUNT; i++) { + pixelsPlane[i] = data[i]; + rowBytesPlane[i] = lineSize[i]; + } } size_t I420Buffer::planeCount() const { - return I420_PLANE_COUNT; + return I420_PLANE_COUNT; } std::shared_ptr I420Buffer::makeTexture(Context* context) const { - if (context == nullptr) { - return nullptr; - } - return YUVTexture::MakeI420(context, colorSpace, colorRange, width(), height(), - const_cast(pixelsPlane), rowBytesPlane); + if (context == nullptr) { + return nullptr; + } + return YUVTexture::MakeI420(context, colorSpace, colorRange, width(), height(), + const_cast(pixelsPlane), rowBytesPlane); } } // namespace pag diff --git a/src/video/I420Buffer.h b/src/video/I420Buffer.h index 5f53d02c20..cd8c1343c4 100644 --- a/src/video/I420Buffer.h +++ b/src/video/I420Buffer.h @@ -22,19 +22,19 @@ namespace pag { class I420Buffer : public VideoBuffer { - public: - size_t planeCount() const override; +public: + size_t planeCount() const override; - std::shared_ptr makeTexture(Context* context) const override; + std::shared_ptr makeTexture(Context* context) const override; - protected: - I420Buffer(int width, int height, uint8_t* data[3], const int lineSize[3], - YUVColorSpace colorSpace, YUVColorRange colorRange); +protected: + I420Buffer(int width, int height, uint8_t* data[3], const int lineSize[3], + YUVColorSpace colorSpace, YUVColorRange colorRange); - private: - YUVColorSpace colorSpace = YUVColorSpace::Rec601; - YUVColorRange colorRange = YUVColorRange::MPEG; - uint8_t* pixelsPlane[3] = {}; - int rowBytesPlane[3] = {}; +private: + YUVColorSpace colorSpace = YUVColorSpace::Rec601; + YUVColorRange colorRange = YUVColorRange::MPEG; + uint8_t* pixelsPlane[3] = {}; + int rowBytesPlane[3] = {}; }; } // namespace pag \ No newline at end of file diff --git a/src/video/MediaDemuxer.cpp b/src/video/MediaDemuxer.cpp index 228da1e78b..c85ff3fe58 100644 --- a/src/video/MediaDemuxer.cpp +++ b/src/video/MediaDemuxer.cpp @@ -24,125 +24,127 @@ namespace pag { * satisfy condition: array[?] <= target and the last one */ int BinarySearch(int start, int end, const std::function& condition) { - while (start <= end) { - int mid = (start + end) / 2; - if (condition(mid)) { - start = mid + 1; - } else { - end = mid - 1; + while (start <= end) { + int mid = (start + end) / 2; + if (condition(mid)) { + start = mid + 1; + } else { + end = mid - 1; + } } - } - return start == 0 ? 0 : start - 1; + return start == 0 ? 0 : start - 1; } int PTSDetail::findKeyframeIndex(int64_t atTime) const { - if (ptsVector.empty()) { - return 0; - } - int start = 0; - auto end = static_cast(keyframeIndexVector.size()) - 1; - return BinarySearch(start, end, [this, atTime](int mid) { - return ptsVector[keyframeIndexVector[mid]] <= atTime; - }); + if (ptsVector.empty()) { + return 0; + } + int start = 0; + auto end = static_cast(keyframeIndexVector.size()) - 1; + return BinarySearch(start, end, [this, atTime](int mid) { + return ptsVector[keyframeIndexVector[mid]] <= atTime; + }); } int64_t PTSDetail::getKeyframeTime(int withKeyframeIndex) const { - if (withKeyframeIndex < 0) { - return INT64_MIN; - } - if (withKeyframeIndex >= static_cast(keyframeIndexVector.size())) { - return INT64_MAX; - } - return ptsVector[keyframeIndexVector[withKeyframeIndex]]; + if (withKeyframeIndex < 0) { + return INT64_MIN; + } + if (withKeyframeIndex >= static_cast(keyframeIndexVector.size())) { + return INT64_MAX; + } + return ptsVector[keyframeIndexVector[withKeyframeIndex]]; } int64_t PTSDetail::getSampleTimeAt(int64_t targetTime) const { - if (targetTime < ptsVector.front()) { - if (targetTime >= 0 && !ptsVector.empty()) { - return ptsVector[0]; + if (targetTime < ptsVector.front()) { + if (targetTime >= 0 && !ptsVector.empty()) { + return ptsVector[0]; + } + return INT64_MIN; } - return INT64_MIN; - } - if (targetTime >= duration) { - return INT64_MAX; - } - auto frameIndex = findFrameIndex(targetTime); - return ptsVector[frameIndex]; + if (targetTime >= duration) { + return INT64_MAX; + } + auto frameIndex = findFrameIndex(targetTime); + return ptsVector[frameIndex]; } int64_t PTSDetail::getNextSampleTimeAt(int64_t targetTime) { - if (targetTime < ptsVector.front()) { - if (targetTime >= 0 && !ptsVector.empty()) { - return ptsVector[0]; + if (targetTime < ptsVector.front()) { + if (targetTime >= 0 && !ptsVector.empty()) { + return ptsVector[0]; + } + return INT64_MAX; + } + if (targetTime >= duration) { + return INT64_MAX; + } + size_t frameIndex = findFrameIndex(targetTime) + 1; + if (frameIndex >= ptsVector.size()) { + return INT64_MAX; } - return INT64_MAX; - } - if (targetTime >= duration) { - return INT64_MAX; - } - size_t frameIndex = findFrameIndex(targetTime) + 1; - if (frameIndex >= ptsVector.size()) { - return INT64_MAX; - } - return ptsVector[frameIndex]; + return ptsVector[frameIndex]; } int PTSDetail::findFrameIndex(int64_t targetTime) const { - auto start = findKeyframeIndex(targetTime); - auto end = start + 1; - start = keyframeIndexVector[start]; - if (end >= static_cast(keyframeIndexVector.size())) { - end = static_cast(ptsVector.size()) - 1; - } else { - end = keyframeIndexVector[end]; - } - return BinarySearch(start, end, - [this, targetTime](int mid) { return ptsVector[mid] <= targetTime; }); + auto start = findKeyframeIndex(targetTime); + auto end = start + 1; + start = keyframeIndexVector[start]; + if (end >= static_cast(keyframeIndexVector.size())) { + end = static_cast(ptsVector.size()) - 1; + } else { + end = keyframeIndexVector[end]; + } + return BinarySearch(start, end, + [this, targetTime](int mid) { + return ptsVector[mid] <= targetTime; + }); } int64_t MediaDemuxer::getSampleTimeAt(int64_t targetTime) { - return ptsDetail()->getSampleTimeAt(targetTime); + return ptsDetail()->getSampleTimeAt(targetTime); } int64_t MediaDemuxer::getNextSampleTimeAt(int64_t targetTime) { - return ptsDetail()->getNextSampleTimeAt(targetTime); + return ptsDetail()->getNextSampleTimeAt(targetTime); } bool MediaDemuxer::trySeek(int64_t targetTime, int64_t currentTime) { - if (currentTime <= targetTime && targetTime < maxPendingTime) { - return false; - } - auto targetKeyframeIndex = ptsDetail()->findKeyframeIndex(targetTime); - if (currentTime <= targetTime && currentKeyframeIndex == targetKeyframeIndex) { - return false; - } - seekTo(ptsDetail()->getKeyframeTime(targetKeyframeIndex)); - return true; + if (currentTime <= targetTime && targetTime < maxPendingTime) { + return false; + } + auto targetKeyframeIndex = ptsDetail()->findKeyframeIndex(targetTime); + if (currentTime <= targetTime && currentKeyframeIndex == targetKeyframeIndex) { + return false; + } + seekTo(ptsDetail()->getKeyframeTime(targetKeyframeIndex)); + return true; } void MediaDemuxer::afterAdvance(bool isKeyframe) { - auto sampleTime = getSampleTime(); - if (maxPendingTime < 0 || maxPendingTime < sampleTime) { - maxPendingTime = sampleTime; - } - if (currentKeyframeIndex < 0) { - currentKeyframeIndex = ptsDetail()->findKeyframeIndex(sampleTime); - } else { - if (isKeyframe) { - ++currentKeyframeIndex; + auto sampleTime = getSampleTime(); + if (maxPendingTime < 0 || maxPendingTime < sampleTime) { + maxPendingTime = sampleTime; + } + if (currentKeyframeIndex < 0) { + currentKeyframeIndex = ptsDetail()->findKeyframeIndex(sampleTime); + } else { + if (isKeyframe) { + ++currentKeyframeIndex; + } } - } } void MediaDemuxer::resetParams() { - maxPendingTime = INT64_MIN; - currentKeyframeIndex = -1; + maxPendingTime = INT64_MIN; + currentKeyframeIndex = -1; } std::shared_ptr MediaDemuxer::ptsDetail() { - if (ptsDetail_ == nullptr) { - ptsDetail_ = createPTSDetail(); - } - return ptsDetail_; + if (ptsDetail_ == nullptr) { + ptsDetail_ = createPTSDetail(); + } + return ptsDetail_; } } // namespace pag diff --git a/src/video/MediaDemuxer.h b/src/video/MediaDemuxer.h index 45fb756dec..958f953b0c 100644 --- a/src/video/MediaDemuxer.h +++ b/src/video/MediaDemuxer.h @@ -23,76 +23,76 @@ namespace pag { class SampleData { - public: - /** - * Compression-encoded data after unpacking. - */ - uint8_t* data = nullptr; - /** - * The size of each compression-encoded data. - */ - size_t length = 0; - - SampleData() = default; - - SampleData(uint8_t* data, int64_t length) : data(data), length(length) { - } - - bool empty() const { - return data == nullptr || length == 0; - } +public: + /** + * Compression-encoded data after unpacking. + */ + uint8_t* data = nullptr; + /** + * The size of each compression-encoded data. + */ + size_t length = 0; + + SampleData() = default; + + SampleData(uint8_t* data, int64_t length) : data(data), length(length) { + } + + bool empty() const { + return data == nullptr || length == 0; + } }; class PTSDetail { - public: - PTSDetail(int64_t duration, std::vector ptsVector, std::vector keyframeIndexVector) - : duration(duration), - ptsVector(std::move(ptsVector)), - keyframeIndexVector(std::move(keyframeIndexVector)) { - } - int64_t duration = 0; - std::vector ptsVector; - std::vector keyframeIndexVector; - - int findKeyframeIndex(int64_t atTime) const; - int64_t getKeyframeTime(int withKeyframeIndex) const; - int64_t getSampleTimeAt(int64_t targetTime) const; - int64_t getNextSampleTimeAt(int64_t targetTime); - - private: - int findFrameIndex(int64_t targetTime) const; +public: + PTSDetail(int64_t duration, std::vector ptsVector, std::vector keyframeIndexVector) + : duration(duration), + ptsVector(std::move(ptsVector)), + keyframeIndexVector(std::move(keyframeIndexVector)) { + } + int64_t duration = 0; + std::vector ptsVector; + std::vector keyframeIndexVector; + + int findKeyframeIndex(int64_t atTime) const; + int64_t getKeyframeTime(int withKeyframeIndex) const; + int64_t getSampleTimeAt(int64_t targetTime) const; + int64_t getNextSampleTimeAt(int64_t targetTime); + +private: + int findFrameIndex(int64_t targetTime) const; }; class MediaDemuxer { - public: - virtual ~MediaDemuxer() = default; +public: + virtual ~MediaDemuxer() = default; - virtual int64_t getSampleTime() = 0; + virtual int64_t getSampleTime() = 0; - virtual bool advance() = 0; + virtual bool advance() = 0; - virtual SampleData readSampleData() = 0; + virtual SampleData readSampleData() = 0; - int64_t getSampleTimeAt(int64_t targetTime); + int64_t getSampleTimeAt(int64_t targetTime); - int64_t getNextSampleTimeAt(int64_t targetTime); + int64_t getNextSampleTimeAt(int64_t targetTime); - bool trySeek(int64_t targetTime, int64_t currentTime); + bool trySeek(int64_t targetTime, int64_t currentTime); - void resetParams(); + void resetParams(); - protected: - virtual void seekTo(int64_t timeUs) = 0; +protected: + virtual void seekTo(int64_t timeUs) = 0; - virtual std::shared_ptr createPTSDetail() = 0; + virtual std::shared_ptr createPTSDetail() = 0; - std::shared_ptr ptsDetail(); + std::shared_ptr ptsDetail(); - void afterAdvance(bool isKeyframe); + void afterAdvance(bool isKeyframe); - private: - std::shared_ptr ptsDetail_ = nullptr; - int64_t maxPendingTime = INT64_MIN; - int currentKeyframeIndex = -1; +private: + std::shared_ptr ptsDetail_ = nullptr; + int64_t maxPendingTime = INT64_MIN; + int currentKeyframeIndex = -1; }; } // namespace pag diff --git a/src/video/SoftAVCDecoder.cpp b/src/video/SoftAVCDecoder.cpp index c2395e094e..615631f5a6 100644 --- a/src/video/SoftAVCDecoder.cpp +++ b/src/video/SoftAVCDecoder.cpp @@ -35,255 +35,255 @@ namespace pag { #ifdef _WIN32 static void* ivd_aligned_malloc(void*, WORD32 alignment, WORD32 size) { - return _aligned_malloc(size, alignment); + return _aligned_malloc(size, alignment); } static void ivd_aligned_free(void*, void* block) { - _aligned_free(block); + _aligned_free(block); } #elif IOS static void* ivd_aligned_malloc(void*, WORD32, WORD32 size) { - return malloc(size); + return malloc(size); } static void ivd_aligned_free(void*, void* block) { - free(block); + free(block); } #else static void* ivd_aligned_malloc(void*, WORD32 alignment, WORD32 size) { - void* buffer = nullptr; - if (posix_memalign(&buffer, alignment, size) != 0) { - return nullptr; - } - return buffer; + void* buffer = nullptr; + if (posix_memalign(&buffer, alignment, size) != 0) { + return nullptr; + } + return buffer; } static void ivd_aligned_free(void*, void* block) { - free(block); + free(block); } #endif bool SoftAVCDecoder::onConfigure(const std::vector& headers, std::string mimeType, int, int) { - if (mimeType != "video/avc") { - return false; - } - if (!initDecoder()) { - return false; - } - size_t totalLength = 0; - for (auto& header : headers) { - totalLength += header.length; - } - headerData = ByteData::Make(totalLength); - size_t pos = 0; - for (auto& header : headers) { - memcpy(headerData->data() + pos, header.data, header.length); - pos += header.length; - } - return openDecoder(); + if (mimeType != "video/avc") { + return false; + } + if (!initDecoder()) { + return false; + } + size_t totalLength = 0; + for (auto& header : headers) { + totalLength += header.length; + } + headerData = ByteData::Make(totalLength); + size_t pos = 0; + for (auto& header : headers) { + memcpy(headerData->data() + pos, header.data, header.length); + pos += header.length; + } + return openDecoder(); } SoftAVCDecoder::~SoftAVCDecoder() { - destroyDecoder(); + destroyDecoder(); } DecoderResult SoftAVCDecoder::onSendBytes(void* bytes, size_t length, int64_t time) { - decodeInput.e_cmd = IVD_CMD_VIDEO_DECODE; - decodeInput.u4_ts = static_cast(time); - decodeInput.pv_stream_buffer = bytes; - decodeInput.u4_num_Bytes = static_cast(length); - decodeInput.u4_size = sizeof(ih264d_video_decode_ip_t); - return DecoderResult::Success; + decodeInput.e_cmd = IVD_CMD_VIDEO_DECODE; + decodeInput.u4_ts = static_cast(time); + decodeInput.pv_stream_buffer = bytes; + decodeInput.u4_num_Bytes = static_cast(length); + decodeInput.u4_size = sizeof(ih264d_video_decode_ip_t); + return DecoderResult::Success; } DecoderResult SoftAVCDecoder::onDecodeFrame() { - flushed = false; - decodeOutput.u4_size = sizeof(ih264d_video_decode_op_t); - auto result = ih264d_api_function(codecContext, &decodeInput, &decodeOutput); - if (result != IV_SUCCESS) { - LOGE("SoftAVCDecoder: Error on sending bytes for decoding, time:%lld \n", time); - return DecoderResult::Error; - } - return decodeOutput.u4_output_present ? DecoderResult::Success : DecoderResult::TryAgainLater; + flushed = false; + decodeOutput.u4_size = sizeof(ih264d_video_decode_op_t); + auto result = ih264d_api_function(codecContext, &decodeInput, &decodeOutput); + if (result != IV_SUCCESS) { + LOGE("SoftAVCDecoder: Error on sending bytes for decoding, time:%lld \n", time); + return DecoderResult::Error; + } + return decodeOutput.u4_output_present ? DecoderResult::Success : DecoderResult::TryAgainLater; } DecoderResult SoftAVCDecoder::onEndOfStream() { - ivd_ctl_flush_ip_t s_ctl_ip = {}; - ivd_ctl_flush_op_t s_ctl_op = {}; - s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; - s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; - s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); - s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t); - auto result = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); - if (result != IV_SUCCESS) { - return DecoderResult::Error; - } - return onSendBytes(nullptr, 0, 0); + ivd_ctl_flush_ip_t s_ctl_ip = {}; + ivd_ctl_flush_op_t s_ctl_op = {}; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; + s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t); + auto result = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); + if (result != IV_SUCCESS) { + return DecoderResult::Error; + } + return onSendBytes(nullptr, 0, 0); } void SoftAVCDecoder::onFlush() { - if (flushed) { - return; - } - resetDecoder(); - openDecoder(); - flushed = true; + if (flushed) { + return; + } + resetDecoder(); + openDecoder(); + flushed = true; } std::unique_ptr SoftAVCDecoder::onRenderFrame() { - if (decodeOutput.u4_output_present == 0) { - return nullptr; - } - auto output = std::make_unique(); - auto& buffer = decodeInput.s_out_buffer; - memcpy(output->data, buffer.pu1_bufs, sizeof(output->data)); - auto format = decodeOutput.s_disp_frm_buf; - output->lineSize[0] = static_cast(format.u4_y_strd); - output->lineSize[1] = static_cast(format.u4_u_strd); - output->lineSize[2] = static_cast(format.u4_v_strd); - return output; + if (decodeOutput.u4_output_present == 0) { + return nullptr; + } + auto output = std::make_unique(); + auto& buffer = decodeInput.s_out_buffer; + memcpy(output->data, buffer.pu1_bufs, sizeof(output->data)); + auto format = decodeOutput.s_disp_frm_buf; + output->lineSize[0] = static_cast(format.u4_y_strd); + output->lineSize[1] = static_cast(format.u4_u_strd); + output->lineSize[2] = static_cast(format.u4_v_strd); + return output; } bool SoftAVCDecoder::initDecoder() { - IV_API_CALL_STATUS_T status; - codecContext = nullptr; - ih264d_create_ip_t s_create_ip; - ih264d_create_op_t s_create_op; - s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t); - s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE; - s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0; - s_create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t); - s_create_ip.s_ivd_create_ip_t.e_output_format = IV_YUV_420P; - s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc; - s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free; - s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr; - status = ih264d_api_function(codecContext, &s_create_ip, &s_create_op); - if (status != IV_SUCCESS) { - LOGE("SoftAVCDecoder: Error on initializing a decoder, error code: 0x%x", - s_create_op.s_ivd_create_op_t.u4_error_code); - destroyDecoder(); + IV_API_CALL_STATUS_T status; codecContext = nullptr; - return false; - } - codecContext = reinterpret_cast(s_create_op.s_ivd_create_op_t.pv_handle); - codecContext->pv_fxns = reinterpret_cast(ih264d_api_function); - codecContext->u4_size = sizeof(iv_obj_t); - return true; + ih264d_create_ip_t s_create_ip; + ih264d_create_op_t s_create_op; + s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ih264d_create_ip_t); + s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE; + s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0; + s_create_op.s_ivd_create_op_t.u4_size = sizeof(ih264d_create_op_t); + s_create_ip.s_ivd_create_ip_t.e_output_format = IV_YUV_420P; + s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc; + s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free; + s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr; + status = ih264d_api_function(codecContext, &s_create_ip, &s_create_op); + if (status != IV_SUCCESS) { + LOGE("SoftAVCDecoder: Error on initializing a decoder, error code: 0x%x", + s_create_op.s_ivd_create_op_t.u4_error_code); + destroyDecoder(); + codecContext = nullptr; + return false; + } + codecContext = reinterpret_cast(s_create_op.s_ivd_create_op_t.pv_handle); + codecContext->pv_fxns = reinterpret_cast(ih264d_api_function); + codecContext->u4_size = sizeof(iv_obj_t); + return true; } bool SoftAVCDecoder::openDecoder() { - if (!setNumCores()) { - return false; - } - if (!setParams(true)) { - return false; - } - onSendBytes(headerData->data(), headerData->length(), 0); - auto result = onDecodeFrame(); - if (result == DecoderResult::Error) { - return false; - } - if (outputFrame == nullptr) { - if (!initOutputFrame()) { - return false; + if (!setNumCores()) { + return false; } - } - flushed = true; - return setParams(false); + if (!setParams(true)) { + return false; + } + onSendBytes(headerData->data(), headerData->length(), 0); + auto result = onDecodeFrame(); + if (result == DecoderResult::Error) { + return false; + } + if (outputFrame == nullptr) { + if (!initOutputFrame()) { + return false; + } + } + flushed = true; + return setParams(false); } bool SoftAVCDecoder::initOutputFrame() { - ivd_ctl_getbufinfo_ip_t s_ctl_ip; - ivd_ctl_getbufinfo_op_t s_ctl_op; - s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; - s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETBUFINFO; - s_ctl_ip.u4_size = sizeof(ivd_ctl_getbufinfo_ip_t); - s_ctl_op.u4_size = sizeof(ivd_ctl_getbufinfo_op_t); - auto status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); - if (status != IV_SUCCESS) { - return false; - } - uint32_t outLength = 0; - for (uint32_t i = 0; i < s_ctl_op.u4_min_num_out_bufs; i++) { - outLength += s_ctl_op.u4_min_out_buf_size[i]; - } - outputFrame = ByteData::Make(outLength); - auto& ps_out_buf = decodeInput.s_out_buffer; - size_t offset = 0; - for (uint32_t i = 0; i < s_ctl_op.u4_min_num_out_bufs; i++) { - ps_out_buf.u4_min_out_buf_size[i] = s_ctl_op.u4_min_out_buf_size[i]; - ps_out_buf.pu1_bufs[i] = outputFrame->data() + offset; - offset += s_ctl_op.u4_min_out_buf_size[i]; - } - ps_out_buf.u4_num_bufs = s_ctl_op.u4_min_num_out_bufs; - return true; + ivd_ctl_getbufinfo_ip_t s_ctl_ip; + ivd_ctl_getbufinfo_op_t s_ctl_op; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETBUFINFO; + s_ctl_ip.u4_size = sizeof(ivd_ctl_getbufinfo_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_getbufinfo_op_t); + auto status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); + if (status != IV_SUCCESS) { + return false; + } + uint32_t outLength = 0; + for (uint32_t i = 0; i < s_ctl_op.u4_min_num_out_bufs; i++) { + outLength += s_ctl_op.u4_min_out_buf_size[i]; + } + outputFrame = ByteData::Make(outLength); + auto& ps_out_buf = decodeInput.s_out_buffer; + size_t offset = 0; + for (uint32_t i = 0; i < s_ctl_op.u4_min_num_out_bufs; i++) { + ps_out_buf.u4_min_out_buf_size[i] = s_ctl_op.u4_min_out_buf_size[i]; + ps_out_buf.pu1_bufs[i] = outputFrame->data() + offset; + offset += s_ctl_op.u4_min_out_buf_size[i]; + } + ps_out_buf.u4_num_bufs = s_ctl_op.u4_min_num_out_bufs; + return true; } void SoftAVCDecoder::resetDecoder() { - ivd_ctl_reset_ip_t s_ctl_ip; - ivd_ctl_reset_op_t s_ctl_op; - IV_API_CALL_STATUS_T status; - s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; - s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET; - s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t); - s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t); - status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); - if (IV_SUCCESS != status) { - LOGE("SoftAVCDecoder: Error on resetting a decoder, error code:: 0x%x", s_ctl_op.u4_error_code); - return; - } + ivd_ctl_reset_ip_t s_ctl_ip; + ivd_ctl_reset_op_t s_ctl_op; + IV_API_CALL_STATUS_T status; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_RESET; + s_ctl_ip.u4_size = sizeof(ivd_ctl_reset_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_reset_op_t); + status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); + if (IV_SUCCESS != status) { + LOGE("SoftAVCDecoder: Error on resetting a decoder, error code:: 0x%x", s_ctl_op.u4_error_code); + return; + } } void SoftAVCDecoder::destroyDecoder() { - IV_API_CALL_STATUS_T status; - if (codecContext) { - ih264d_delete_ip_t s_delete_ip; - ih264d_delete_op_t s_delete_op; - s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ih264d_delete_ip_t); - s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE; - s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ih264d_delete_op_t); - status = ih264d_api_function(codecContext, &s_delete_ip, &s_delete_op); - if (status != IV_SUCCESS) { - LOGE("SoftAVCDecoder: Error on destroying a decoder, error code: 0x%x", - s_delete_op.s_ivd_delete_op_t.u4_error_code); + IV_API_CALL_STATUS_T status; + if (codecContext) { + ih264d_delete_ip_t s_delete_ip; + ih264d_delete_op_t s_delete_op; + s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ih264d_delete_ip_t); + s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE; + s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ih264d_delete_op_t); + status = ih264d_api_function(codecContext, &s_delete_ip, &s_delete_op); + if (status != IV_SUCCESS) { + LOGE("SoftAVCDecoder: Error on destroying a decoder, error code: 0x%x", + s_delete_op.s_ivd_delete_op_t.u4_error_code); + } } - } } bool SoftAVCDecoder::setParams(bool decodeHeader) { - ivd_ctl_set_config_ip_t s_ctl_ip; - ivd_ctl_set_config_op_t s_ctl_op; - s_ctl_ip.u4_disp_wd = 0; - s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; - s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; - s_ctl_ip.e_vid_dec_mode = decodeHeader ? IVD_DECODE_HEADER : IVD_DECODE_FRAME; - s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; - s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; - s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); - s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); - auto status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); - if (status != IV_SUCCESS) { - LOGE("SoftAVCDecoder: Error on setting the stride: 0x%x", s_ctl_op.u4_error_code); - } - return status == IV_SUCCESS; + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + s_ctl_ip.u4_disp_wd = 0; + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = decodeHeader ? IVD_DECODE_HEADER : IVD_DECODE_FRAME; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + auto status = ih264d_api_function(codecContext, &s_ctl_ip, &s_ctl_op); + if (status != IV_SUCCESS) { + LOGE("SoftAVCDecoder: Error on setting the stride: 0x%x", s_ctl_op.u4_error_code); + } + return status == IV_SUCCESS; } bool SoftAVCDecoder::setNumCores() { - ih264d_ctl_set_num_cores_ip_t s_set_cores_ip; - ih264d_ctl_set_num_cores_op_t s_set_cores_op; - s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; - s_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES; - s_set_cores_ip.u4_num_cores = 1; - s_set_cores_ip.u4_size = sizeof(ih264d_ctl_set_num_cores_ip_t); - s_set_cores_op.u4_size = sizeof(ih264d_ctl_set_num_cores_op_t); - auto status = ih264d_api_function(codecContext, &s_set_cores_ip, &s_set_cores_op); - if (IV_SUCCESS != status) { - LOGE("SoftAVCDecoder: Error on setting number of cores: 0x%x", s_set_cores_op.u4_error_code); - } - return status == IV_SUCCESS; + ih264d_ctl_set_num_cores_ip_t s_set_cores_ip; + ih264d_ctl_set_num_cores_op_t s_set_cores_op; + s_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES; + s_set_cores_ip.u4_num_cores = 1; + s_set_cores_ip.u4_size = sizeof(ih264d_ctl_set_num_cores_ip_t); + s_set_cores_op.u4_size = sizeof(ih264d_ctl_set_num_cores_op_t); + auto status = ih264d_api_function(codecContext, &s_set_cores_ip, &s_set_cores_op); + if (IV_SUCCESS != status) { + LOGE("SoftAVCDecoder: Error on setting number of cores: 0x%x", s_set_cores_op.u4_error_code); + } + return status == IV_SUCCESS; } } // namespace pag diff --git a/src/video/SoftAVCDecoder.h b/src/video/SoftAVCDecoder.h index 5806cebd1f..d2b14ac184 100644 --- a/src/video/SoftAVCDecoder.h +++ b/src/video/SoftAVCDecoder.h @@ -40,37 +40,37 @@ namespace pag { * SoftAVCDecoder supports the annex-b format only. */ class SoftAVCDecoder : public SoftwareDecoder { - public: - ~SoftAVCDecoder() override; +public: + ~SoftAVCDecoder() override; - bool onConfigure(const std::vector& headers, std::string mime, int width, - int height) override; + bool onConfigure(const std::vector& headers, std::string mime, int width, + int height) override; - DecoderResult onSendBytes(void* bytes, size_t length, int64_t frame) override; + DecoderResult onSendBytes(void* bytes, size_t length, int64_t frame) override; - DecoderResult onDecodeFrame() override; + DecoderResult onDecodeFrame() override; - DecoderResult onEndOfStream() override; + DecoderResult onEndOfStream() override; - void onFlush() override; + void onFlush() override; - std::unique_ptr onRenderFrame() override; + std::unique_ptr onRenderFrame() override; - private: - std::unique_ptr headerData = nullptr; - std::unique_ptr outputFrame = nullptr; - iv_obj_t* codecContext = nullptr; // Codec context - ivd_video_decode_ip_t decodeInput = {}; - ivd_video_decode_op_t decodeOutput = {}; - bool flushed = true; +private: + std::unique_ptr headerData = nullptr; + std::unique_ptr outputFrame = nullptr; + iv_obj_t* codecContext = nullptr; // Codec context + ivd_video_decode_ip_t decodeInput = {}; + ivd_video_decode_op_t decodeOutput = {}; + bool flushed = true; - bool initDecoder(); - bool openDecoder(); - bool setParams(bool decodeHeader); - bool setNumCores(); - bool initOutputFrame(); - void destroyDecoder(); - void resetDecoder(); + bool initDecoder(); + bool openDecoder(); + bool setParams(bool decodeHeader); + bool setNumCores(); + bool initOutputFrame(); + void destroyDecoder(); + void resetDecoder(); }; } // namespace pag diff --git a/src/video/SoftwareDecoderWrapper.cpp b/src/video/SoftwareDecoderWrapper.cpp index f9a3d824c8..1c27e67656 100644 --- a/src/video/SoftwareDecoderWrapper.cpp +++ b/src/video/SoftwareDecoderWrapper.cpp @@ -22,38 +22,38 @@ namespace pag { class SoftwareI420Buffer : public I420Buffer { - public: - static std::shared_ptr Make( - int width, int height, uint8_t* data[3], const int lineSize[3], YUVColorSpace colorSpace, - YUVColorRange colorRange, std::shared_ptr softwareDecoder) { - auto buffer = new SoftwareI420Buffer(width, height, data, lineSize, colorSpace, colorRange, - std::move(softwareDecoder)); - return std::shared_ptr(buffer); - } - - private: - // hold a reference to software decoder in case it is released before us. - std::shared_ptr softwareDecoder = nullptr; - - SoftwareI420Buffer(int width, int height, uint8_t* data[3], const int lineSize[3], - YUVColorSpace colorSpace, YUVColorRange colorRange, - std::shared_ptr softwareDecoder) - : I420Buffer(width, height, data, lineSize, colorSpace, colorRange), - softwareDecoder(std::move(softwareDecoder)) { - } +public: + static std::shared_ptr Make( + int width, int height, uint8_t* data[3], const int lineSize[3], YUVColorSpace colorSpace, + YUVColorRange colorRange, std::shared_ptr softwareDecoder) { + auto buffer = new SoftwareI420Buffer(width, height, data, lineSize, colorSpace, colorRange, + std::move(softwareDecoder)); + return std::shared_ptr(buffer); + } + +private: + // hold a reference to software decoder in case it is released before us. + std::shared_ptr softwareDecoder = nullptr; + + SoftwareI420Buffer(int width, int height, uint8_t* data[3], const int lineSize[3], + YUVColorSpace colorSpace, YUVColorRange colorRange, + std::shared_ptr softwareDecoder) + : I420Buffer(width, height, data, lineSize, colorSpace, colorRange), + softwareDecoder(std::move(softwareDecoder)) { + } }; std::unique_ptr SoftwareDecoderWrapper::Wrap( std::shared_ptr softwareDecoder, const VideoConfig& config) { - if (softwareDecoder == nullptr) { - return nullptr; - } - auto decoder = new SoftwareDecoderWrapper(std::move(softwareDecoder)); - if (!decoder->onConfigure(config)) { - delete decoder; - return nullptr; - } - return std::unique_ptr(decoder); + if (softwareDecoder == nullptr) { + return nullptr; + } + auto decoder = new SoftwareDecoderWrapper(std::move(softwareDecoder)); + if (!decoder->onConfigure(config)) { + delete decoder; + return nullptr; + } + return std::unique_ptr(decoder); } SoftwareDecoderWrapper::SoftwareDecoderWrapper(std::shared_ptr externalDecoder) @@ -61,121 +61,121 @@ SoftwareDecoderWrapper::SoftwareDecoderWrapper(std::shared_ptr } SoftwareDecoderWrapper::~SoftwareDecoderWrapper() { - delete frameBytes; - pendingFrames.clear(); + delete frameBytes; + pendingFrames.clear(); } bool SoftwareDecoderWrapper::onConfigure(const VideoConfig& config) { - videoConfig = config; - if (Platform::Current()->naluType() != NALUType::AnnexB) { - // External decoders only support AnnexB format. - videoConfig.headers.clear(); - for (auto& header : config.headers) { - if (header->length() <= 4) { - return false; - } - auto newHeader = ByteData::Make(header->length()); - auto bytes = newHeader->data(); - bytes[0] = 0; - bytes[1] = 0; - bytes[2] = 0; - bytes[3] = 1; - memcpy(bytes + 4, header->data() + 4, header->length() - 4); - videoConfig.headers.push_back(std::move(newHeader)); + videoConfig = config; + if (Platform::Current()->naluType() != NALUType::AnnexB) { + // External decoders only support AnnexB format. + videoConfig.headers.clear(); + for (auto& header : config.headers) { + if (header->length() <= 4) { + return false; + } + auto newHeader = ByteData::Make(header->length()); + auto bytes = newHeader->data(); + bytes[0] = 0; + bytes[1] = 0; + bytes[2] = 0; + bytes[3] = 1; + memcpy(bytes + 4, header->data() + 4, header->length() - 4); + videoConfig.headers.push_back(std::move(newHeader)); + } + } + std::vector codecHeaders = {}; + for (auto& header : videoConfig.headers) { + HeaderData newHeader = {}; + newHeader.data = header->data(); + newHeader.length = header->length(); + codecHeaders.push_back(newHeader); } - } - std::vector codecHeaders = {}; - for (auto& header : videoConfig.headers) { - HeaderData newHeader = {}; - newHeader.data = header->data(); - newHeader.length = header->length(); - codecHeaders.push_back(newHeader); - } - return softwareDecoder->onConfigure(codecHeaders, videoConfig.mimeType, videoConfig.width, - videoConfig.height); + return softwareDecoder->onConfigure(codecHeaders, videoConfig.mimeType, videoConfig.width, + videoConfig.height); } DecodingResult SoftwareDecoderWrapper::onSendBytes(void* bytes, size_t length, int64_t time) { - DecodingResult result = DecodingResult::Error; - if (softwareDecoder != nullptr) { - // External decoders only support AnnexB format. - if (bytes != nullptr && length > 0 && Platform::Current()->naluType() != NALUType::AnnexB) { - if (frameBytes != nullptr && frameLength < length) { - delete frameBytes; - frameBytes = nullptr; - } - uint32_t pos = 0; - if (frameBytes == nullptr) { - frameBytes = new uint8_t[length]; - frameLength = length; - } - while (pos < length) { - frameBytes[pos] = 0; - frameBytes[pos + 1] = 0; - frameBytes[pos + 2] = 0; - frameBytes[pos + 3] = 1; - uint32_t NALULength = (static_cast(bytes)[pos] << 24) + - (static_cast(bytes)[pos + 1] << 16) + - (static_cast(bytes)[pos + 2] << 8) + - static_cast(bytes)[pos + 3]; - pos += 4; - memcpy(frameBytes + pos, static_cast(bytes) + pos, NALULength); - pos += NALULength; - } - - result = static_cast(softwareDecoder->onSendBytes(frameBytes, length, time)); - } else { - result = static_cast(softwareDecoder->onSendBytes(bytes, length, time)); + DecodingResult result = DecodingResult::Error; + if (softwareDecoder != nullptr) { + // External decoders only support AnnexB format. + if (bytes != nullptr && length > 0 && Platform::Current()->naluType() != NALUType::AnnexB) { + if (frameBytes != nullptr && frameLength < length) { + delete frameBytes; + frameBytes = nullptr; + } + uint32_t pos = 0; + if (frameBytes == nullptr) { + frameBytes = new uint8_t[length]; + frameLength = length; + } + while (pos < length) { + frameBytes[pos] = 0; + frameBytes[pos + 1] = 0; + frameBytes[pos + 2] = 0; + frameBytes[pos + 3] = 1; + uint32_t NALULength = (static_cast(bytes)[pos] << 24) + + (static_cast(bytes)[pos + 1] << 16) + + (static_cast(bytes)[pos + 2] << 8) + + static_cast(bytes)[pos + 3]; + pos += 4; + memcpy(frameBytes + pos, static_cast(bytes) + pos, NALULength); + pos += NALULength; + } + + result = static_cast(softwareDecoder->onSendBytes(frameBytes, length, time)); + } else { + result = static_cast(softwareDecoder->onSendBytes(bytes, length, time)); + } + + if (result != DecodingResult::Error) { + pendingFrames.push_back(time); + } } - - if (result != DecodingResult::Error) { - pendingFrames.push_back(time); - } - } - return result; + return result; } DecodingResult SoftwareDecoderWrapper::onDecodeFrame() { - DecodingResult result = DecodingResult::Error; - if (softwareDecoder != nullptr) { - result = static_cast(softwareDecoder->onDecodeFrame()); - currentDecodedTime = -1; - if (result == DecodingResult::Success) { - if (!pendingFrames.empty()) { - pendingFrames.sort(); - currentDecodedTime = pendingFrames.front(); - pendingFrames.pop_front(); - } + DecodingResult result = DecodingResult::Error; + if (softwareDecoder != nullptr) { + result = static_cast(softwareDecoder->onDecodeFrame()); + currentDecodedTime = -1; + if (result == DecodingResult::Success) { + if (!pendingFrames.empty()) { + pendingFrames.sort(); + currentDecodedTime = pendingFrames.front(); + pendingFrames.pop_front(); + } + } } - } - return result; + return result; } void SoftwareDecoderWrapper::onFlush() { - softwareDecoder->onFlush(); - pendingFrames.clear(); - currentDecodedTime = -1; + softwareDecoder->onFlush(); + pendingFrames.clear(); + currentDecodedTime = -1; } DecodingResult SoftwareDecoderWrapper::onEndOfStream() { - DecodingResult result = DecodingResult::Error; - if (softwareDecoder != nullptr) { - result = static_cast(softwareDecoder->onEndOfStream()); - } - return result; + DecodingResult result = DecodingResult::Error; + if (softwareDecoder != nullptr) { + result = static_cast(softwareDecoder->onEndOfStream()); + } + return result; } std::shared_ptr SoftwareDecoderWrapper::onRenderFrame() { - auto frame = softwareDecoder->onRenderFrame(); - if (frame == nullptr) { - return nullptr; - } - return SoftwareI420Buffer::Make(videoConfig.width, videoConfig.height, frame->data, - frame->lineSize, videoConfig.colorSpace, videoConfig.colorRange, - softwareDecoder); + auto frame = softwareDecoder->onRenderFrame(); + if (frame == nullptr) { + return nullptr; + } + return SoftwareI420Buffer::Make(videoConfig.width, videoConfig.height, frame->data, + frame->lineSize, videoConfig.colorSpace, videoConfig.colorRange, + softwareDecoder); } int64_t SoftwareDecoderWrapper::presentationTime() { - return currentDecodedTime; + return currentDecodedTime; } } // namespace pag diff --git a/src/video/SoftwareDecoderWrapper.h b/src/video/SoftwareDecoderWrapper.h index b09b30c2e3..661d1b20ac 100644 --- a/src/video/SoftwareDecoderWrapper.h +++ b/src/video/SoftwareDecoderWrapper.h @@ -24,34 +24,34 @@ namespace pag { class SoftwareDecoderWrapper : public VideoDecoder { - public: - static std::unique_ptr Wrap(std::shared_ptr softwareDecoder, - const VideoConfig& config); +public: + static std::unique_ptr Wrap(std::shared_ptr softwareDecoder, + const VideoConfig& config); - ~SoftwareDecoderWrapper() override; + ~SoftwareDecoderWrapper() override; - bool onConfigure(const VideoConfig& config); + bool onConfigure(const VideoConfig& config); - DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; + DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) override; - DecodingResult onEndOfStream() override; + DecodingResult onEndOfStream() override; - DecodingResult onDecodeFrame() override; + DecodingResult onDecodeFrame() override; - void onFlush() override; + void onFlush() override; - std::shared_ptr onRenderFrame() override; + std::shared_ptr onRenderFrame() override; - int64_t presentationTime() override; + int64_t presentationTime() override; - private: - std::shared_ptr softwareDecoder = nullptr; - VideoConfig videoConfig = {}; - uint8_t* frameBytes = nullptr; - size_t frameLength = 0; - int64_t currentDecodedTime = -1; - std::list pendingFrames{}; +private: + std::shared_ptr softwareDecoder = nullptr; + VideoConfig videoConfig = {}; + uint8_t* frameBytes = nullptr; + size_t frameLength = 0; + int64_t currentDecodedTime = -1; + std::list pendingFrames{}; - explicit SoftwareDecoderWrapper(std::shared_ptr externalDecoder); + explicit SoftwareDecoderWrapper(std::shared_ptr externalDecoder); }; } // namespace pag diff --git a/src/video/VideoBuffer.h b/src/video/VideoBuffer.h index 0416959e3b..7e3b700f7a 100644 --- a/src/video/VideoBuffer.h +++ b/src/video/VideoBuffer.h @@ -26,14 +26,14 @@ namespace pag { * VideoBuffer describes a two dimensional array of pixels from a decoded video frame. */ class VideoBuffer : public TextureBuffer { - public: - /** - * Returns number of planes in this video buffer. - */ - virtual size_t planeCount() const = 0; +public: + /** + * Returns number of planes in this video buffer. + */ + virtual size_t planeCount() const = 0; - protected: - VideoBuffer(int width, int height) : TextureBuffer(width, height) { - } +protected: + VideoBuffer(int width, int height) : TextureBuffer(width, height) { + } }; } // namespace pag \ No newline at end of file diff --git a/src/video/VideoDecoder.cpp b/src/video/VideoDecoder.cpp index 42a6bab390..26947dd360 100644 --- a/src/video/VideoDecoder.cpp +++ b/src/video/VideoDecoder.cpp @@ -30,81 +30,81 @@ static std::atomic_int maxHardwareDecoderCount = {65535}; static std::atomic_int globalGPUDecoderCount = {0}; void PAGVideoDecoder::SetMaxHardwareDecoderCount(int count) { - maxHardwareDecoderCount = count; + maxHardwareDecoderCount = count; } void PAGVideoDecoder::RegisterSoftwareDecoderFactory(SoftwareDecoderFactory* decoderFactory) { - softwareDecoderFactory = decoderFactory; + softwareDecoderFactory = decoderFactory; } bool VideoDecoder::HasHardwareDecoder() { - return Platform::Current()->hasHardwareDecoder(); + return Platform::Current()->hasHardwareDecoder(); } int VideoDecoder::GetMaxHardwareDecoderCount() { - return maxHardwareDecoderCount; + return maxHardwareDecoderCount; } bool VideoDecoder::HasSoftwareDecoder() { #ifdef PAG_USE_LIBAVC - return true; + return true; #else - return softwareDecoderFactory != nullptr; + return softwareDecoderFactory != nullptr; #endif } bool VideoDecoder::HasExternalSoftwareDecoder() { - return softwareDecoderFactory != nullptr; + return softwareDecoderFactory != nullptr; } SoftwareDecoderFactory* VideoDecoder::GetExternalSoftwareDecoderFactory() { - return softwareDecoderFactory; + return softwareDecoderFactory; } std::unique_ptr VideoDecoder::CreateHardwareDecoder(const VideoConfig& config) { - std::unique_ptr videoDecoder = nullptr; - if (globalGPUDecoderCount < VideoDecoder::GetMaxHardwareDecoderCount()) { - videoDecoder = Platform::Current()->makeHardwareDecoder(config); - } - if (videoDecoder != nullptr) { - globalGPUDecoderCount++; - videoDecoder->hardwareBacked = true; - } - return videoDecoder; + std::unique_ptr videoDecoder = nullptr; + if (globalGPUDecoderCount < VideoDecoder::GetMaxHardwareDecoderCount()) { + videoDecoder = Platform::Current()->makeHardwareDecoder(config); + } + if (videoDecoder != nullptr) { + globalGPUDecoderCount++; + videoDecoder->hardwareBacked = true; + } + return videoDecoder; } std::unique_ptr VideoDecoder::CreateSoftwareDecoder(const VideoConfig& config) { - std::unique_ptr videoDecoder = nullptr; - SoftwareDecoderFactory* factory = softwareDecoderFactory; - if (factory != nullptr) { - videoDecoder = SoftwareDecoderWrapper::Wrap(factory->createSoftwareDecoder(), config); - } + std::unique_ptr videoDecoder = nullptr; + SoftwareDecoderFactory* factory = softwareDecoderFactory; + if (factory != nullptr) { + videoDecoder = SoftwareDecoderWrapper::Wrap(factory->createSoftwareDecoder(), config); + } #ifdef PAG_USE_LIBAVC - if (videoDecoder == nullptr) { - videoDecoder = SoftwareDecoderWrapper::Wrap(std::make_unique(), config); - if (videoDecoder != nullptr) { - LOGI("All other video decoders are not available, fallback to SoftAVCDecoder!"); + if (videoDecoder == nullptr) { + videoDecoder = SoftwareDecoderWrapper::Wrap(std::make_unique(), config); + if (videoDecoder != nullptr) { + LOGI("All other video decoders are not available, fallback to SoftAVCDecoder!"); + } } - } #endif - if (videoDecoder != nullptr) { - videoDecoder->hardwareBacked = false; - } else { - LOGE("Failed on creating a software video decoder!"); - } - return videoDecoder; + if (videoDecoder != nullptr) { + videoDecoder->hardwareBacked = false; + } else { + LOGE("Failed on creating a software video decoder!"); + } + return videoDecoder; } std::unique_ptr VideoDecoder::Make(const VideoConfig& config, bool useHardware) { - return useHardware ? CreateHardwareDecoder(config) : CreateSoftwareDecoder(config); + return useHardware ? CreateHardwareDecoder(config) : CreateSoftwareDecoder(config); } VideoDecoder::~VideoDecoder() { - if (hardwareBacked) { - globalGPUDecoderCount--; - } + if (hardwareBacked) { + globalGPUDecoderCount--; + } } } // namespace pag \ No newline at end of file diff --git a/src/video/VideoDecoder.h b/src/video/VideoDecoder.h index 2909efaf32..f0354aa547 100644 --- a/src/video/VideoDecoder.h +++ b/src/video/VideoDecoder.h @@ -26,102 +26,102 @@ namespace pag { enum class DecodingResult { - Success = 0, - TryAgainLater = -1, - Error = -2, - EndOfStream = -3, + Success = 0, + TryAgainLater = -1, + Error = -2, + EndOfStream = -3, }; struct VideoConfig { - int width = 0; - int height = 0; - float frameRate = 0.0; - bool hasAlpha = false; - std::vector> headers = {}; - YUVColorSpace colorSpace = YUVColorSpace::Rec601; - YUVColorRange colorRange = YUVColorRange::MPEG; - std::string mimeType = "video/avc"; + int width = 0; + int height = 0; + float frameRate = 0.0; + bool hasAlpha = false; + std::vector> headers = {}; + YUVColorSpace colorSpace = YUVColorSpace::Rec601; + YUVColorRange colorRange = YUVColorRange::MPEG; + std::string mimeType = "video/avc"; }; class VideoDecoder { - public: - /** - * Returns true if hardware video decoders are supported on current platform. - */ - static bool HasHardwareDecoder(); - - /** - * Returns true if software video decoders are supported on current platform. - */ - static bool HasSoftwareDecoder(); - - /** - * Returns true if a external software decoder is registered. We assume that it has better - * performance than libavc. - */ - static bool HasExternalSoftwareDecoder(); - - /** - * Returns the registered SoftwareDecoderFactory. - */ - static SoftwareDecoderFactory* GetExternalSoftwareDecoderFactory(); - - /** - * Returns the maximum number of hardware video decoders we can create. - */ - static int GetMaxHardwareDecoderCount(); - - /** - * Creates a new video decoder by specified type. Returns a hardware video decoder if useHardware - * is true, otherwise, returns a software video decoder. - */ - static std::unique_ptr Make(const VideoConfig& config, bool useHardware); - - virtual ~VideoDecoder(); - - /** - * Returns true if this is a hardware video decoder. - */ - bool isHardwareBacked() const { - return hardwareBacked; - } - - /** - * Send a frame of bytes for decoding. The same bytes will be sent next time if it returns - * DecodingResult::TryAgainLater - */ - virtual DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) = 0; - - /** - * Called to notify there is no more frame bytes available. - */ - virtual DecodingResult onEndOfStream() = 0; - - /** - * Try to decode a new frame from the pending frames sent by onSendBytes(). More pending - * frames will be sent by onSendBytes() if it returns DecodingResult::TryAgainLater. - */ - virtual DecodingResult onDecodeFrame() = 0; - - /** - * Called when seeking happens to clear all pending frames. - */ - virtual void onFlush() = 0; - - /** - * Returns decoded video frame to render. - */ - virtual std::shared_ptr onRenderFrame() = 0; - - /** - * Returns current presentation time. - */ - virtual int64_t presentationTime() = 0; - - private: - bool hardwareBacked = false; - - static std::unique_ptr CreateHardwareDecoder(const VideoConfig& config); - static std::unique_ptr CreateSoftwareDecoder(const VideoConfig& config); +public: + /** + * Returns true if hardware video decoders are supported on current platform. + */ + static bool HasHardwareDecoder(); + + /** + * Returns true if software video decoders are supported on current platform. + */ + static bool HasSoftwareDecoder(); + + /** + * Returns true if a external software decoder is registered. We assume that it has better + * performance than libavc. + */ + static bool HasExternalSoftwareDecoder(); + + /** + * Returns the registered SoftwareDecoderFactory. + */ + static SoftwareDecoderFactory* GetExternalSoftwareDecoderFactory(); + + /** + * Returns the maximum number of hardware video decoders we can create. + */ + static int GetMaxHardwareDecoderCount(); + + /** + * Creates a new video decoder by specified type. Returns a hardware video decoder if useHardware + * is true, otherwise, returns a software video decoder. + */ + static std::unique_ptr Make(const VideoConfig& config, bool useHardware); + + virtual ~VideoDecoder(); + + /** + * Returns true if this is a hardware video decoder. + */ + bool isHardwareBacked() const { + return hardwareBacked; + } + + /** + * Send a frame of bytes for decoding. The same bytes will be sent next time if it returns + * DecodingResult::TryAgainLater + */ + virtual DecodingResult onSendBytes(void* bytes, size_t length, int64_t time) = 0; + + /** + * Called to notify there is no more frame bytes available. + */ + virtual DecodingResult onEndOfStream() = 0; + + /** + * Try to decode a new frame from the pending frames sent by onSendBytes(). More pending + * frames will be sent by onSendBytes() if it returns DecodingResult::TryAgainLater. + */ + virtual DecodingResult onDecodeFrame() = 0; + + /** + * Called when seeking happens to clear all pending frames. + */ + virtual void onFlush() = 0; + + /** + * Returns decoded video frame to render. + */ + virtual std::shared_ptr onRenderFrame() = 0; + + /** + * Returns current presentation time. + */ + virtual int64_t presentationTime() = 0; + +private: + bool hardwareBacked = false; + + static std::unique_ptr CreateHardwareDecoder(const VideoConfig& config); + static std::unique_ptr CreateSoftwareDecoder(const VideoConfig& config); }; } // namespace pag diff --git a/src/video/VideoDecodingTask.cpp b/src/video/VideoDecodingTask.cpp index c6daf79237..a338aa8eab 100644 --- a/src/video/VideoDecodingTask.cpp +++ b/src/video/VideoDecodingTask.cpp @@ -20,13 +20,13 @@ namespace pag { std::shared_ptr VideoDecodingTask::MakeAndRun(VideoReader* reader, int64_t targetTime) { - if (reader == nullptr) { - return nullptr; - } - auto task = - Task::Make(std::unique_ptr(new VideoDecodingTask(reader, targetTime))); - task->run(); - return task; + if (reader == nullptr) { + return nullptr; + } + auto task = + Task::Make(std::unique_ptr(new VideoDecodingTask(reader, targetTime))); + task->run(); + return task; } VideoDecodingTask::VideoDecodingTask(VideoReader* reader, int64_t targetTime) @@ -34,7 +34,7 @@ VideoDecodingTask::VideoDecodingTask(VideoReader* reader, int64_t targetTime) } void VideoDecodingTask::execute() { - reader->readSample(targetTime); + reader->readSample(targetTime); } } // namespace pag \ No newline at end of file diff --git a/src/video/VideoDecodingTask.h b/src/video/VideoDecodingTask.h index 295896d342..148e176fc3 100644 --- a/src/video/VideoDecodingTask.h +++ b/src/video/VideoDecodingTask.h @@ -23,14 +23,14 @@ namespace pag { class VideoDecodingTask : public Executor { - public: - static std::shared_ptr MakeAndRun(VideoReader* reader, int64_t targetTime); +public: + static std::shared_ptr MakeAndRun(VideoReader* reader, int64_t targetTime); - private: - VideoReader* reader = nullptr; - int64_t targetTime = 0; +private: + VideoReader* reader = nullptr; + int64_t targetTime = 0; - VideoDecodingTask(VideoReader* reader, int64_t targetTime); - void execute() override; + VideoDecodingTask(VideoReader* reader, int64_t targetTime); + void execute() override; }; } // namespace pag diff --git a/src/video/VideoReader.cpp b/src/video/VideoReader.cpp index 4030cf0402..8e6092d23a 100644 --- a/src/video/VideoReader.cpp +++ b/src/video/VideoReader.cpp @@ -27,285 +27,285 @@ namespace pag { #define FORCE_SOFTWARE_SIZE 160000 // 400x400 class GPUDecoderTask : public Executor { - public: - static std::shared_ptr MakeAndRun(const VideoConfig& config) { - auto task = Task::Make(std::unique_ptr(new GPUDecoderTask(config))); - task->run(); - return task; - } +public: + static std::shared_ptr MakeAndRun(const VideoConfig& config) { + auto task = Task::Make(std::unique_ptr(new GPUDecoderTask(config))); + task->run(); + return task; + } - std::unique_ptr getDecoder() { - return std::move(videoDecoder); - } + std::unique_ptr getDecoder() { + return std::move(videoDecoder); + } - private: - VideoConfig videoConfig = {}; - std::unique_ptr videoDecoder = nullptr; +private: + VideoConfig videoConfig = {}; + std::unique_ptr videoDecoder = nullptr; - explicit GPUDecoderTask(VideoConfig config) : videoConfig(std::move(config)) { - } + explicit GPUDecoderTask(VideoConfig config) : videoConfig(std::move(config)) { + } - void execute() override { - videoDecoder = VideoDecoder::Make(videoConfig, true); - } + void execute() override { + videoDecoder = VideoDecoder::Make(videoConfig, true); + } }; VideoReader::VideoReader(VideoConfig config, std::unique_ptr demuxer, DecodingPolicy policy) : videoConfig(std::move(config)), demuxer(demuxer.release()) { - if (videoConfig.width * videoConfig.height <= FORCE_SOFTWARE_SIZE) { - // force using software decoder if the size of video is less than 400x400 for better - // performance。 - policy = DecodingPolicy::Software; - } - decoderTypeIndex = DECODER_TYPE_HARDWARE; - switch (policy) { + if (videoConfig.width * videoConfig.height <= FORCE_SOFTWARE_SIZE) { + // force using software decoder if the size of video is less than 400x400 for better + // performance。 + policy = DecodingPolicy::Software; + } + decoderTypeIndex = DECODER_TYPE_HARDWARE; + switch (policy) { case DecodingPolicy::Software: - // Force using software decoders only when external decoders are available, because the - // built-in libavc has poor performance. - if (VideoDecoder::HasExternalSoftwareDecoder()) { - decoderTypeIndex = DECODER_TYPE_SOFTWARE; - } - break; + // Force using software decoders only when external decoders are available, because the + // built-in libavc has poor performance. + if (VideoDecoder::HasExternalSoftwareDecoder()) { + decoderTypeIndex = DECODER_TYPE_SOFTWARE; + } + break; case DecodingPolicy::SoftwareToHardware: - if (VideoDecoder::HasExternalSoftwareDecoder() && VideoDecoder::HasHardwareDecoder()) { - decoderTypeIndex = DECODER_TYPE_SOFTWARE; - gpuDecoderTask = GPUDecoderTask::MakeAndRun(videoConfig); - } - break; + if (VideoDecoder::HasExternalSoftwareDecoder() && VideoDecoder::HasHardwareDecoder()) { + decoderTypeIndex = DECODER_TYPE_SOFTWARE; + gpuDecoderTask = GPUDecoderTask::MakeAndRun(videoConfig); + } + break; default: - break; - } + break; + } } VideoReader::~VideoReader() { - destroyVideoDecoder(); - delete demuxer; + destroyVideoDecoder(); + delete demuxer; } bool VideoReader::decodeFrame(int64_t sampleTime) { - tryMakeVideoDecoder(); - if (videoDecoder == nullptr) { - return false; - } - auto success = onDecodeFrame(sampleTime); - if (!success) { - // retry once. - resetParams(); - success = onDecodeFrame(sampleTime); + tryMakeVideoDecoder(); + if (videoDecoder == nullptr) { + return false; + } + auto success = onDecodeFrame(sampleTime); if (!success) { - // fallback to software decoder. - destroyVideoDecoder(); - decoderTypeIndex++; - tryMakeVideoDecoder(); - if (videoDecoder) { + // retry once. + resetParams(); success = onDecodeFrame(sampleTime); - } + if (!success) { + // fallback to software decoder. + destroyVideoDecoder(); + decoderTypeIndex++; + tryMakeVideoDecoder(); + if (videoDecoder) { + success = onDecodeFrame(sampleTime); + } + } + } + if (!success) { + LOGE("VideoDecoder: Error on decoding frame.\n"); } - } - if (!success) { - LOGE("VideoDecoder: Error on decoding frame.\n"); - } - return success; + return success; } int64_t VideoReader::getSampleTimeAt(int64_t targetTime) { - std::lock_guard autoLock(locker); - return demuxer->getSampleTimeAt(targetTime); + std::lock_guard autoLock(locker); + return demuxer->getSampleTimeAt(targetTime); } int64_t VideoReader::getNextSampleTimeAt(int64_t targetTime) { - std::lock_guard autoLock(locker); - return demuxer->getNextSampleTimeAt(targetTime); + std::lock_guard autoLock(locker); + return demuxer->getNextSampleTimeAt(targetTime); } void VideoReader::recordPerformance(Performance* performance, int64_t decodingTime) { - if (performance) { - if (decoderTypeIndex == DECODER_TYPE_HARDWARE) { - performance->hardwareDecodingTime += decodingTime; - performance->hardwareDecodingInitialTime += hardDecodingInitialTime; - hardDecodingInitialTime = 0; // 只记录一次。 - } else { - performance->softwareDecodingTime += decodingTime; - performance->softwareDecodingInitialTime += softDecodingInitialTime; - softDecodingInitialTime = 0; + if (performance) { + if (decoderTypeIndex == DECODER_TYPE_HARDWARE) { + performance->hardwareDecodingTime += decodingTime; + performance->hardwareDecodingInitialTime += hardDecodingInitialTime; + hardDecodingInitialTime = 0; // 只记录一次。 + } else { + performance->softwareDecodingTime += decodingTime; + performance->softwareDecodingInitialTime += softDecodingInitialTime; + softDecodingInitialTime = 0; + } } - } } std::shared_ptr VideoReader::readSample(int64_t targetTime) { - // Need a locker here in case there are other threads are decoding at the same time. - std::lock_guard autoLock(locker); - auto sampleTime = demuxer->getSampleTimeAt(targetTime); - if (sampleTime == currentRenderedTime) { - return outputBuffer; - } + // Need a locker here in case there are other threads are decoding at the same time. + std::lock_guard autoLock(locker); + auto sampleTime = demuxer->getSampleTimeAt(targetTime); + if (sampleTime == currentRenderedTime) { + return outputBuffer; + } - if (!renderFrame(sampleTime)) { - destroyVideoDecoder(); - decoderTypeIndex++; if (!renderFrame(sampleTime)) { - return nullptr; + destroyVideoDecoder(); + decoderTypeIndex++; + if (!renderFrame(sampleTime)) { + return nullptr; + } } - } - return outputBuffer; + return outputBuffer; } bool VideoReader::sendData() { - if (inputEndOfStream) { - return true; - } - if (needsAdvance) { - demuxer->advance(); - needsAdvance = false; - } - auto data = demuxer->readSampleData(); - if (data.length <= 0) { - auto result = videoDecoder->onEndOfStream(); - if (result == DecodingResult::Error) { - return false; - } else if (result == DecodingResult::Success) { - inputEndOfStream = true; + if (inputEndOfStream) { + return true; + } + if (needsAdvance) { + demuxer->advance(); + needsAdvance = false; } - } else { - auto sampleTime = demuxer->getSampleTime(); - auto result = videoDecoder->onSendBytes(data.data, data.length, sampleTime); - if (result == DecodingResult::Error) { - LOGE("VideoReader: Error on sending bytes for decoding.\n"); - return false; - } else if (result == DecodingResult::Success) { - needsAdvance = true; - return true; + auto data = demuxer->readSampleData(); + if (data.length <= 0) { + auto result = videoDecoder->onEndOfStream(); + if (result == DecodingResult::Error) { + return false; + } else if (result == DecodingResult::Success) { + inputEndOfStream = true; + } + } else { + auto sampleTime = demuxer->getSampleTime(); + auto result = videoDecoder->onSendBytes(data.data, data.length, sampleTime); + if (result == DecodingResult::Error) { + LOGE("VideoReader: Error on sending bytes for decoding.\n"); + return false; + } else if (result == DecodingResult::Success) { + needsAdvance = true; + return true; + } } - } - return true; + return true; } bool VideoReader::onDecodeFrame(int64_t sampleTime) { - if (demuxer->trySeek(sampleTime, currentDecodedTime)) { - resetParams(); - needsAdvance = true; - videoDecoder->onFlush(); - } - int tryDecodeCount = 0; - while (currentDecodedTime < sampleTime) { - if (!sendData()) { - return false; + if (demuxer->trySeek(sampleTime, currentDecodedTime)) { + resetParams(); + needsAdvance = true; + videoDecoder->onFlush(); } - auto result = videoDecoder->onDecodeFrame(); - if (result == DecodingResult::Error) { - return false; - } else if (result == DecodingResult::Success) { - tryDecodeCount = 0; - currentDecodedTime = videoDecoder->presentationTime(); - } else if (result == DecodingResult::EndOfStream) { - outputEndOfStream = true; - return true; - } else if (result == DecodingResult::TryAgainLater) { - if ((tryDecodeCount++) >= MAX_TRY_DECODE_COUNT) { - LOGE("VideoDecoder: try decoding frame count reach limit %d.\n", MAX_TRY_DECODE_COUNT); - return false; - } + int tryDecodeCount = 0; + while (currentDecodedTime < sampleTime) { + if (!sendData()) { + return false; + } + auto result = videoDecoder->onDecodeFrame(); + if (result == DecodingResult::Error) { + return false; + } else if (result == DecodingResult::Success) { + tryDecodeCount = 0; + currentDecodedTime = videoDecoder->presentationTime(); + } else if (result == DecodingResult::EndOfStream) { + outputEndOfStream = true; + return true; + } else if (result == DecodingResult::TryAgainLater) { + if ((tryDecodeCount++) >= MAX_TRY_DECODE_COUNT) { + LOGE("VideoDecoder: try decoding frame count reach limit %d.\n", MAX_TRY_DECODE_COUNT); + return false; + } + } } - } - return true; + return true; } void VideoReader::tryMakeVideoDecoder() { - if (gpuDecoderTask && !gpuDecoderTask->isRunning()) { - if (switchToGPUDecoderOfTask()) { - return; + if (gpuDecoderTask && !gpuDecoderTask->isRunning()) { + if (switchToGPUDecoderOfTask()) { + return; + } + } + if (videoDecoder) { + return; + } + videoDecoder = makeDecoder(); + if (videoDecoder) { + return; } - } - if (videoDecoder) { - return; - } - videoDecoder = makeDecoder(); - if (videoDecoder) { - return; - } - if (gpuDecoderTask && switchToGPUDecoderOfTask()) { - return; - } - decoderTypeIndex = DECODER_TYPE_FAIL; + if (gpuDecoderTask && switchToGPUDecoderOfTask()) { + return; + } + decoderTypeIndex = DECODER_TYPE_FAIL; } void VideoReader::destroyVideoDecoder() { - if (videoDecoder == nullptr) { - return; - } - delete videoDecoder; - videoDecoder = nullptr; - outputBuffer = nullptr; - currentRenderedTime = INT64_MIN; - resetParams(); + if (videoDecoder == nullptr) { + return; + } + delete videoDecoder; + videoDecoder = nullptr; + outputBuffer = nullptr; + currentRenderedTime = INT64_MIN; + resetParams(); } void VideoReader::resetParams() { - currentDecodedTime = INT64_MIN; - outputEndOfStream = false; - needsAdvance = false; - inputEndOfStream = false; - demuxer->resetParams(); + currentDecodedTime = INT64_MIN; + outputEndOfStream = false; + needsAdvance = false; + inputEndOfStream = false; + demuxer->resetParams(); } bool VideoReader::switchToGPUDecoderOfTask() { - destroyVideoDecoder(); - auto executor = gpuDecoderTask->wait(); - videoDecoder = static_cast(executor)->getDecoder().release(); - gpuDecoderTask = nullptr; - if (videoDecoder) { - decoderTypeIndex = DECODER_TYPE_HARDWARE; - return true; - } - return false; + destroyVideoDecoder(); + auto executor = gpuDecoderTask->wait(); + videoDecoder = static_cast(executor)->getDecoder().release(); + gpuDecoderTask = nullptr; + if (videoDecoder) { + decoderTypeIndex = DECODER_TYPE_HARDWARE; + return true; + } + return false; } bool VideoReader::renderFrame(int64_t sampleTime) { - if (sampleTime == currentDecodedTime) { - return true; - } - if (!decodeFrame(sampleTime)) { - outputBuffer = nullptr; - currentRenderedTime = INT64_MIN; - return false; - } - if (outputEndOfStream) { - return true; - } - outputBuffer = videoDecoder->onRenderFrame(); - if (outputBuffer) { - currentRenderedTime = currentDecodedTime; - } else { - currentRenderedTime = INT64_MIN; - } - return outputBuffer != nullptr; + if (sampleTime == currentDecodedTime) { + return true; + } + if (!decodeFrame(sampleTime)) { + outputBuffer = nullptr; + currentRenderedTime = INT64_MIN; + return false; + } + if (outputEndOfStream) { + return true; + } + outputBuffer = videoDecoder->onRenderFrame(); + if (outputBuffer) { + currentRenderedTime = currentDecodedTime; + } else { + currentRenderedTime = INT64_MIN; + } + return outputBuffer != nullptr; } VideoDecoder* VideoReader::makeDecoder() { - VideoDecoder* decoder = nullptr; - if (decoderTypeIndex <= DECODER_TYPE_HARDWARE) { - int64_t initialStartTime = GetTimer(); - // try hardware decoder. - decoder = VideoDecoder::Make(videoConfig, true).release(); - hardDecodingInitialTime = GetTimer() - initialStartTime; - if (decoder) { - decoderTypeIndex = DECODER_TYPE_HARDWARE; - return decoder; + VideoDecoder* decoder = nullptr; + if (decoderTypeIndex <= DECODER_TYPE_HARDWARE) { + int64_t initialStartTime = GetTimer(); + // try hardware decoder. + decoder = VideoDecoder::Make(videoConfig, true).release(); + hardDecodingInitialTime = GetTimer() - initialStartTime; + if (decoder) { + decoderTypeIndex = DECODER_TYPE_HARDWARE; + return decoder; + } } - } - if (decoderTypeIndex <= DECODER_TYPE_SOFTWARE) { - int64_t initialStartTime = GetTimer(); - // try software decoder. - decoder = VideoDecoder::Make(videoConfig, false).release(); - softDecodingInitialTime = GetTimer() - initialStartTime; - if (decoder) { - decoderTypeIndex = DECODER_TYPE_SOFTWARE; - return decoder; + if (decoderTypeIndex <= DECODER_TYPE_SOFTWARE) { + int64_t initialStartTime = GetTimer(); + // try software decoder. + decoder = VideoDecoder::Make(videoConfig, false).release(); + softDecodingInitialTime = GetTimer() - initialStartTime; + if (decoder) { + decoderTypeIndex = DECODER_TYPE_SOFTWARE; + return decoder; + } } - } - return decoder; + return decoder; } } // namespace pag diff --git a/src/video/VideoReader.h b/src/video/VideoReader.h index c6b5f5de0d..888faef53b 100644 --- a/src/video/VideoReader.h +++ b/src/video/VideoReader.h @@ -26,57 +26,57 @@ namespace pag { class VideoReader { - public: - VideoReader(VideoConfig videoConfig, std::unique_ptr demuxer, - DecodingPolicy policy = DecodingPolicy::Hardware); +public: + VideoReader(VideoConfig videoConfig, std::unique_ptr demuxer, + DecodingPolicy policy = DecodingPolicy::Hardware); - ~VideoReader(); + ~VideoReader(); - int64_t getSampleTimeAt(int64_t targetTime); + int64_t getSampleTimeAt(int64_t targetTime); - /** - * 如果不存在有效的下一帧,返回 INT64_MAX。 - */ - int64_t getNextSampleTimeAt(int64_t targetTime); + /** + * 如果不存在有效的下一帧,返回 INT64_MAX。 + */ + int64_t getNextSampleTimeAt(int64_t targetTime); - std::shared_ptr readSample(int64_t targetTime); + std::shared_ptr readSample(int64_t targetTime); - void recordPerformance(Performance* performance, int64_t decodingTime); + void recordPerformance(Performance* performance, int64_t decodingTime); - private: - std::mutex locker = {}; - VideoConfig videoConfig = {}; - MediaDemuxer* demuxer = nullptr; - std::shared_ptr gpuDecoderTask = nullptr; - VideoDecoder* videoDecoder = nullptr; - int decoderTypeIndex = 0; +private: + std::mutex locker = {}; + VideoConfig videoConfig = {}; + MediaDemuxer* demuxer = nullptr; + std::shared_ptr gpuDecoderTask = nullptr; + VideoDecoder* videoDecoder = nullptr; + int decoderTypeIndex = 0; - std::shared_ptr outputBuffer = nullptr; - bool outputEndOfStream = false; - bool needsAdvance = false; - bool inputEndOfStream = false; - int64_t currentDecodedTime = INT64_MIN; - int64_t currentRenderedTime = INT64_MIN; + std::shared_ptr outputBuffer = nullptr; + bool outputEndOfStream = false; + bool needsAdvance = false; + bool inputEndOfStream = false; + int64_t currentDecodedTime = INT64_MIN; + int64_t currentRenderedTime = INT64_MIN; - int64_t hardDecodingInitialTime = 0; - int64_t softDecodingInitialTime = 0; + int64_t hardDecodingInitialTime = 0; + int64_t softDecodingInitialTime = 0; - void destroyVideoDecoder(); + void destroyVideoDecoder(); - void tryMakeVideoDecoder(); + void tryMakeVideoDecoder(); - void resetParams(); + void resetParams(); - bool sendData(); + bool sendData(); - bool decodeFrame(int64_t sampleTime); + bool decodeFrame(int64_t sampleTime); - bool onDecodeFrame(int64_t sampleTime); + bool onDecodeFrame(int64_t sampleTime); - bool switchToGPUDecoderOfTask(); + bool switchToGPUDecoderOfTask(); - bool renderFrame(int64_t sampleTime); + bool renderFrame(int64_t sampleTime); - VideoDecoder* makeDecoder(); + VideoDecoder* makeDecoder(); }; } // namespace pag diff --git a/src/video/VideoSequenceDemuxer.cpp b/src/video/VideoSequenceDemuxer.cpp index 0f6276e426..3157ec5494 100644 --- a/src/video/VideoSequenceDemuxer.cpp +++ b/src/video/VideoSequenceDemuxer.cpp @@ -25,74 +25,75 @@ VideoSequenceDemuxer::VideoSequenceDemuxer(VideoSequence* sequence) : sequence(s } void VideoSequenceDemuxer::seekTo(int64_t timeUs) { - if (timeUs < 0) { - return; - } - auto keyframeIndex = ptsDetail()->findKeyframeIndex(timeUs); - seekFrameIndex = ptsDetail()->keyframeIndexVector[keyframeIndex]; + if (timeUs < 0) { + return; + } + auto keyframeIndex = ptsDetail()->findKeyframeIndex(timeUs); + seekFrameIndex = ptsDetail()->keyframeIndexVector[keyframeIndex]; } int64_t VideoSequenceDemuxer::getSampleTime() { - auto totalFrames = static_cast(sequence->frames.size()); - if (currentFrameIndex >= totalFrames) { - return INT64_MAX; - } - return FrameToTime(sequence->frames[currentFrameIndex]->frame, sequence->frameRate); + auto totalFrames = static_cast(sequence->frames.size()); + if (currentFrameIndex >= totalFrames) { + return INT64_MAX; + } + return FrameToTime(sequence->frames[currentFrameIndex]->frame, sequence->frameRate); } bool VideoSequenceDemuxer::advance() { - if (seekFrameIndex >= 0) { - currentFrameIndex = seekFrameIndex; - seekFrameIndex = INT_MIN; - } else { - if (currentFrameIndex >= static_cast(sequence->frames.size())) { - return false; + if (seekFrameIndex >= 0) { + currentFrameIndex = seekFrameIndex; + seekFrameIndex = INT_MIN; + } else { + if (currentFrameIndex >= static_cast(sequence->frames.size())) { + return false; + } + ++currentFrameIndex; + } + if (currentFrameIndex < static_cast(sequence->frames.size())) { + afterAdvance(sequence->frames[currentFrameIndex]->isKeyframe); } - ++currentFrameIndex; - } - if (currentFrameIndex < static_cast(sequence->frames.size())) { - afterAdvance(sequence->frames[currentFrameIndex]->isKeyframe); - } - return true; + return true; } SampleData VideoSequenceDemuxer::readSampleData() { - if (currentFrameIndex >= static_cast(sequence->frames.size())) { - return {}; - } - auto data = sequence->frames[currentFrameIndex]->fileBytes; - SampleData sampleData = {}; - sampleData.data = data->data(); - sampleData.length = data->length(); - return sampleData; + if (currentFrameIndex >= static_cast(sequence->frames.size())) { + return {}; + } + auto data = sequence->frames[currentFrameIndex]->fileBytes; + SampleData sampleData = {}; + sampleData.data = data->data(); + sampleData.length = data->length(); + return sampleData; } std::shared_ptr VideoSequenceDemuxer::createPTSDetail() { - std::vector keyframeIndexVector{}; - auto totalFrames = static_cast(sequence->frames.size()); - std::list ptsList{}; - for (int i = totalFrames - 1; i >= 0; --i) { - auto videoFrame = sequence->frames[i]; - auto pts = FrameToTime(videoFrame->frame, sequence->frameRate); - int index = 0; - auto it = ptsList.begin(); - for (; it != ptsList.end(); ++it) { - if (*it < pts) { - ++index; - continue; - } - break; - } - ptsList.insert(it, pts); - if (videoFrame->isKeyframe) { - index = totalFrames - (static_cast(ptsList.size()) - index); - keyframeIndexVector.insert(keyframeIndexVector.begin(), index); + std::vector keyframeIndexVector{}; + auto totalFrames = static_cast(sequence->frames.size()); + std::list ptsList{}; + for (int i = totalFrames - 1; i >= 0; --i) { + auto videoFrame = sequence->frames[i]; + auto pts = FrameToTime(videoFrame->frame, sequence->frameRate); + int index = 0; + auto it = ptsList.begin(); + for (; it != ptsList.end(); ++it) { + if (*it < pts) { + ++index; + continue; + } + break; + } + ptsList.insert(it, pts); + if (videoFrame->isKeyframe) { + index = totalFrames - (static_cast(ptsList.size()) - index); + keyframeIndexVector.insert(keyframeIndexVector.begin(), index); + } } - } - auto duration = FrameToTime(sequence->duration(), sequence->frameRate); - auto ptsVector = std::vector{std::make_move_iterator(ptsList.begin()), - std::make_move_iterator(ptsList.end())}; - return std::make_shared(duration, std::move(ptsVector), - std::move(keyframeIndexVector)); + auto duration = FrameToTime(sequence->duration(), sequence->frameRate); + auto ptsVector = std::vector {std::make_move_iterator(ptsList.begin()), + std::make_move_iterator(ptsList.end()) + }; + return std::make_shared(duration, std::move(ptsVector), + std::move(keyframeIndexVector)); } } // namespace pag diff --git a/src/video/VideoSequenceDemuxer.h b/src/video/VideoSequenceDemuxer.h index 4ecd1c97b5..dfd621bff5 100644 --- a/src/video/VideoSequenceDemuxer.h +++ b/src/video/VideoSequenceDemuxer.h @@ -24,22 +24,22 @@ namespace pag { class VideoSequenceDemuxer : public MediaDemuxer { - public: - explicit VideoSequenceDemuxer(VideoSequence* sequence); +public: + explicit VideoSequenceDemuxer(VideoSequence* sequence); - void seekTo(int64_t timeUs) override; + void seekTo(int64_t timeUs) override; - int64_t getSampleTime() override; + int64_t getSampleTime() override; - bool advance() override; + bool advance() override; - SampleData readSampleData() override; + SampleData readSampleData() override; - private: - VideoSequence* sequence; - int seekFrameIndex = INT_MIN; - int currentFrameIndex = 0; +private: + VideoSequence* sequence; + int seekFrameIndex = INT_MIN; + int currentFrameIndex = 0; - std::shared_ptr createPTSDetail() override; + std::shared_ptr createPTSDetail() override; }; } // namespace pag diff --git a/src/video/VideoSequenceReader.cpp b/src/video/VideoSequenceReader.cpp index 4107a6483f..12d7a7cfa6 100644 --- a/src/video/VideoSequenceReader.cpp +++ b/src/video/VideoSequenceReader.cpp @@ -22,83 +22,83 @@ namespace pag { std::shared_ptr SequenceReader::Make(std::shared_ptr file, - VideoSequence* sequence, - DecodingPolicy policy) { - return std::make_shared(std::move(file), sequence, policy); + VideoSequence* sequence, + DecodingPolicy policy) { + return std::make_shared(std::move(file), sequence, policy); } VideoSequenceReader::VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, - DecodingPolicy policy) + DecodingPolicy policy) : SequenceReader(std::move(file), sequence) { - VideoConfig config = {}; - auto demuxer = std::make_unique(sequence); - config.hasAlpha = sequence->alphaStartX + sequence->alphaStartY > 0; - config.width = sequence->alphaStartX + sequence->width; - if (config.width % 2 == 1) { - config.width++; - } - config.height = sequence->alphaStartY + sequence->height; - if (config.height % 2 == 1) { - config.height++; - } - for (auto& header : sequence->headers) { - auto bytes = ByteData::MakeWithoutCopy(header->data(), header->length()); - config.headers.push_back(std::move(bytes)); - } - config.mimeType = "video/avc"; - config.colorSpace = YUVColorSpace::Rec601; - config.frameRate = sequence->frameRate; - reader = std::make_unique(config, std::move(demuxer), policy); + VideoConfig config = {}; + auto demuxer = std::make_unique(sequence); + config.hasAlpha = sequence->alphaStartX + sequence->alphaStartY > 0; + config.width = sequence->alphaStartX + sequence->width; + if (config.width % 2 == 1) { + config.width++; + } + config.height = sequence->alphaStartY + sequence->height; + if (config.height % 2 == 1) { + config.height++; + } + for (auto& header : sequence->headers) { + auto bytes = ByteData::MakeWithoutCopy(header->data(), header->length()); + config.headers.push_back(std::move(bytes)); + } + config.mimeType = "video/avc"; + config.colorSpace = YUVColorSpace::Rec601; + config.frameRate = sequence->frameRate; + reader = std::make_unique(config, std::move(demuxer), policy); } void VideoSequenceReader::prepareAsync(Frame targetFrame) { - if (!reader) { - return; - } - auto targetTime = FrameToTime(targetFrame, sequence->frameRate); - if (lastTask != nullptr) { - if (lastFrame != -1) { - pendingTime = targetTime; + if (!reader) { + return; + } + auto targetTime = FrameToTime(targetFrame, sequence->frameRate); + if (lastTask != nullptr) { + if (lastFrame != -1) { + pendingTime = targetTime; + } + } else { + lastTask = VideoDecodingTask::MakeAndRun(reader.get(), targetTime); } - } else { - lastTask = VideoDecodingTask::MakeAndRun(reader.get(), targetTime); - } } std::shared_ptr VideoSequenceReader::readTexture(Frame targetFrame, RenderCache* cache) { - if (!reader) { - return nullptr; - } - if (lastFrame == targetFrame) { - return lastTexture; - } - auto startTime = GetTimer(); - // setting task to nullptr triggers cancel(), in case the bitmap content changes before we - // makeTexture(). - lastTask = nullptr; - auto targetTime = FrameToTime(targetFrame, sequence->frameRate); - auto buffer = reader->readSample(targetTime); - auto decodingTime = GetTimer() - startTime; - reader->recordPerformance(cache, decodingTime); - lastTexture = nullptr; // Release the last texture for reusing in context. - lastFrame = -1; - if (buffer) { - startTime = GetTimer(); - lastTexture = buffer->makeTexture(cache->getContext()); - lastFrame = targetFrame; - cache->textureUploadingTime += GetTimer() - startTime; - if (!staticContent) { - auto nextSampleTime = reader->getNextSampleTimeAt(targetTime); - if (nextSampleTime == INT64_MAX && pendingTime >= 0) { - // Add preparation for the first frame when reach to the end. - nextSampleTime = pendingTime; - pendingTime = -1; - } - if (nextSampleTime != INT64_MAX) { - lastTask = VideoDecodingTask::MakeAndRun(reader.get(), nextSampleTime); - } + if (!reader) { + return nullptr; + } + if (lastFrame == targetFrame) { + return lastTexture; } - } - return lastTexture; + auto startTime = GetTimer(); + // setting task to nullptr triggers cancel(), in case the bitmap content changes before we + // makeTexture(). + lastTask = nullptr; + auto targetTime = FrameToTime(targetFrame, sequence->frameRate); + auto buffer = reader->readSample(targetTime); + auto decodingTime = GetTimer() - startTime; + reader->recordPerformance(cache, decodingTime); + lastTexture = nullptr; // Release the last texture for reusing in context. + lastFrame = -1; + if (buffer) { + startTime = GetTimer(); + lastTexture = buffer->makeTexture(cache->getContext()); + lastFrame = targetFrame; + cache->textureUploadingTime += GetTimer() - startTime; + if (!staticContent) { + auto nextSampleTime = reader->getNextSampleTimeAt(targetTime); + if (nextSampleTime == INT64_MAX && pendingTime >= 0) { + // Add preparation for the first frame when reach to the end. + nextSampleTime = pendingTime; + pendingTime = -1; + } + if (nextSampleTime != INT64_MAX) { + lastTask = VideoDecodingTask::MakeAndRun(reader.get(), nextSampleTime); + } + } + } + return lastTexture; } } // namespace pag diff --git a/src/video/VideoSequenceReader.h b/src/video/VideoSequenceReader.h index 085c1c0f71..03fe59587b 100644 --- a/src/video/VideoSequenceReader.h +++ b/src/video/VideoSequenceReader.h @@ -25,18 +25,18 @@ namespace pag { class VideoSequenceReader : public SequenceReader { - public: - VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy policy); +public: + VideoSequenceReader(std::shared_ptr file, VideoSequence* sequence, DecodingPolicy policy); - void prepareAsync(Frame targetFrame) override; + void prepareAsync(Frame targetFrame) override; - std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) override; + std::shared_ptr readTexture(Frame targetFrame, RenderCache* cache) override; - private: - Frame lastFrame = -1; - int64_t pendingTime = -1; - std::shared_ptr reader = nullptr; - std::shared_ptr lastTexture = nullptr; - std::shared_ptr lastTask = nullptr; +private: + Frame lastFrame = -1; + int64_t pendingTime = -1; + std::shared_ptr reader = nullptr; + std::shared_ptr lastTexture = nullptr; + std::shared_ptr lastTask = nullptr; }; } // namespace pag diff --git a/test/AsyncDecodeTest.cpp b/test/AsyncDecodeTest.cpp index fdc93275ca..89cf5da306 100644 --- a/test/AsyncDecodeTest.cpp +++ b/test/AsyncDecodeTest.cpp @@ -29,174 +29,175 @@ PAG_TEST_CASE_WITH_PATH(AsyncDecode, "../resources/apitest/AsyncDecodeTest.pag") * 用例描述: 异步解码时候同步删除图层 */ PAG_TEST_F(AsyncDecode, remove_ID79139135) { - // 触发第一个视频图层初始化 - TestPAGPlayer->flush(); - // 移除所有图层 - TestPAGPlayer->getComposition()->removeAllLayers(); - // 需要再次flush,因为缓存是在flush时候才会删除 - TestPAGPlayer->flush(); + // 触发第一个视频图层初始化 + TestPAGPlayer->flush(); + // 移除所有图层 + TestPAGPlayer->getComposition()->removeAllLayers(); + // 需要再次flush,因为缓存是在flush时候才会删除 + TestPAGPlayer->flush(); - // 图像销毁时候,异步正在初始化的序列帧也应该被销毁 - EXPECT_EQ(static_cast(TestPAGPlayer->renderCache->sequenceCaches.size()), 0); + // 图像销毁时候,异步正在初始化的序列帧也应该被销毁 + EXPECT_EQ(static_cast(TestPAGPlayer->renderCache->sequenceCaches.size()), 0); } /** * 用例描述: 校验异步预测是否能正常命中和回收 */ PAG_TEST_F(AsyncDecode, init_ID79139125) { - int currentFrame = 0; - auto root = TestPAGPlayer->getComposition(); - auto renderCache = TestPAGPlayer->renderCache; - while (currentFrame < root->stretchedFrameDuration()) { - switch (currentFrame) { - case 0: - //落入第一个视频的预测区间的范围 - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - break; - case 1: - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - case 58: - //位于静态区间,并且开始进入下个图层的预测范围 - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - break; - case 115: - //第二个图层开始效果 - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 0); - break; - case 145: - // 开始循环 - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - // 走到这里就直接return,不需要执行后续帧的测试了 - return; + int currentFrame = 0; + auto root = TestPAGPlayer->getComposition(); + auto renderCache = TestPAGPlayer->renderCache; + while (currentFrame < root->stretchedFrameDuration()) { + switch (currentFrame) { + case 0: + //落入第一个视频的预测区间的范围 + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + break; + case 1: + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + case 58: + //位于静态区间,并且开始进入下个图层的预测范围 + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + break; + case 115: + //第二个图层开始效果 + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 0); + break; + case 145: + // 开始循环 + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + // 走到这里就直接return,不需要执行后续帧的测试了 + return; + } + TestPAGPlayer->nextFrame(); + currentFrame++; } - TestPAGPlayer->nextFrame(); - currentFrame++; - } } /** * 用例描述: 校验当视频图层不用以后是否能立马回收 */ PAG_TEST_F(AsyncDecode, destory_ID79139125) { - int currentFrame = 0; - auto root = TestPAGPlayer->getComposition(); - while (currentFrame < root->stretchedFrameDuration()) { - switch (currentFrame) { - case 41: - //第一个图层开始销毁 - TestPAGPlayer->flush(); - EXPECT_EQ(static_cast(TestPAGPlayer->renderCache->sequenceCaches.size()), 0); - return; + int currentFrame = 0; + auto root = TestPAGPlayer->getComposition(); + while (currentFrame < root->stretchedFrameDuration()) { + switch (currentFrame) { + case 41: + //第一个图层开始销毁 + TestPAGPlayer->flush(); + EXPECT_EQ(static_cast(TestPAGPlayer->renderCache->sequenceCaches.size()), 0); + return; + } + TestPAGPlayer->nextFrame(); + currentFrame++; } - TestPAGPlayer->nextFrame(); - currentFrame++; - } } /** * 用例描述: 验证当触发异步加载以后,立马销毁资源场景 */ PAG_TEST_F(AsyncDecode, release_ID79427343) { - TestPAGPlayer->flush(); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - TestPAGPlayer->setComposition(nullptr); - TestPAGFile = nullptr; - TestPAGPlayer->flush(); + TestPAGPlayer->flush(); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + TestPAGPlayer->setComposition(nullptr); + TestPAGFile = nullptr; + TestPAGPlayer->flush(); } /** * 用例描述: 位图序列帧异步解码校验 */ PAG_TEST_F(AsyncDecode, bitmapCompDecodeTest) { - // 25--------------------------60 - // 5----------------------45 - auto pagFile = PAGFile::Load("../resources/apitest/BitmapComp.pag"); - EXPECT_TRUE(pagFile != nullptr); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - int currentFrame = 0; - auto renderCache = TestPAGPlayer->renderCache; - while (currentFrame < pagFile->stretchedFrameDuration()) { - TestPAGPlayer->flush(); - switch (currentFrame) { - case 0: - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - break; - case 10: - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); - break; - case 44: - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); - break; - case 45: - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); - break; - case 50: - // 开始循环预测 - EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); - break; - default: - break; + // 25--------------------------60 + // 5----------------------45 + auto pagFile = PAGFile::Load("../resources/apitest/BitmapComp.pag"); + EXPECT_TRUE(pagFile != nullptr); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + int currentFrame = 0; + auto renderCache = TestPAGPlayer->renderCache; + while (currentFrame < pagFile->stretchedFrameDuration()) { + TestPAGPlayer->flush(); + switch (currentFrame) { + case 0: + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + break; + case 10: + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); + break; + case 44: + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); + break; + case 45: + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 1); + break; + case 50: + // 开始循环预测 + EXPECT_EQ(static_cast(renderCache->sequenceCaches.size()), 2); + break; + default: + break; + } + TestPAGPlayer->nextFrame(); + currentFrame++; } - TestPAGPlayer->nextFrame(); - currentFrame++; - } } /** * 用例描述: 图片异步解码校验 */ PAG_TEST_F(AsyncDecode, imageDecodeTest) { - // 0----------15 - // 10-----------35 - // 40---------60 - auto pagFile = PAGFile::Load("../resources/apitest/ImageDecodeTest.pag"); - EXPECT_TRUE(pagFile != nullptr); - auto pagImage = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); - pagFile->replaceImage(1, pagImage); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - int currentFrame = 0; - auto renderCache = TestPAGPlayer->renderCache; - while (currentFrame < pagFile->stretchedFrameDuration()) { - TestPAGPlayer->flush(); - switch (currentFrame) { - case 0: { - ASSERT_EQ(static_cast(renderCache->imageTasks.size()), 1); - auto bitmapID = renderCache->imageTasks.begin()->first; - EXPECT_EQ(bitmapID, pagImage->uniqueID()); - } break; - case 9: - EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); - break; - case 10: - ASSERT_EQ(static_cast(renderCache->imageTasks.size()), 0); - break; - case 25: - // 进入第三个图片的预测 - EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); - break; - case 39: - EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); - break; - case 40: - EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 0); - break; - case 45: - // 开始循环预测, 本应该是 1,但是第一张图的缓存还存在,所以这里是 0. - EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 0); - break; - default: - break; + // 0----------15 + // 10-----------35 + // 40---------60 + auto pagFile = PAGFile::Load("../resources/apitest/ImageDecodeTest.pag"); + EXPECT_TRUE(pagFile != nullptr); + auto pagImage = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); + pagFile->replaceImage(1, pagImage); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + int currentFrame = 0; + auto renderCache = TestPAGPlayer->renderCache; + while (currentFrame < pagFile->stretchedFrameDuration()) { + TestPAGPlayer->flush(); + switch (currentFrame) { + case 0: { + ASSERT_EQ(static_cast(renderCache->imageTasks.size()), 1); + auto bitmapID = renderCache->imageTasks.begin()->first; + EXPECT_EQ(bitmapID, pagImage->uniqueID()); + } + break; + case 9: + EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); + break; + case 10: + ASSERT_EQ(static_cast(renderCache->imageTasks.size()), 0); + break; + case 25: + // 进入第三个图片的预测 + EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); + break; + case 39: + EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 1); + break; + case 40: + EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 0); + break; + case 45: + // 开始循环预测, 本应该是 1,但是第一张图的缓存还存在,所以这里是 0. + EXPECT_EQ(static_cast(renderCache->imageTasks.size()), 0); + break; + default: + break; + } + TestPAGPlayer->nextFrame(); + currentFrame++; } - TestPAGPlayer->nextFrame(); - currentFrame++; - } } } // namespace pag diff --git a/test/GLUtilTest.cpp b/test/GLUtilTest.cpp index ac53c757b4..94995094ee 100644 --- a/test/GLUtilTest.cpp +++ b/test/GLUtilTest.cpp @@ -34,103 +34,103 @@ std::vector> vendors = { {"Imagination Technologies", GLVendor::Imagination}, }; const unsigned char* glGetStringMock(unsigned name) { - if (name == GL::VENDOR) { - return reinterpret_cast(vendors[i].first.c_str()); - } else if (name == GL::VERSION) { - if (i != 0) { - return reinterpret_cast("2.0"); - } else { - return reinterpret_cast("5.0"); + if (name == GL::VENDOR) { + return reinterpret_cast(vendors[i].first.c_str()); + } else if (name == GL::VERSION) { + if (i != 0) { + return reinterpret_cast("2.0"); + } else { + return reinterpret_cast("5.0"); + } } - } - return nullptr; + return nullptr; } void getIntegervMock(unsigned pname, int* params) { - if (pname == GL::MAX_TEXTURE_SIZE) { - *params = 1024; - } + if (pname == GL::MAX_TEXTURE_SIZE) { + *params = 1024; + } } void glGetInternalformativMock(unsigned target, unsigned, unsigned pname, int, int* params) { - if (target != GL::RENDERBUFFER) { - return; - } - if (pname == GL::NUM_SAMPLE_COUNTS) { - *params = 2; - return; - } - if (pname == GL::SAMPLES) { - params[0] = 4; - params[1] = 8; - } + if (target != GL::RENDERBUFFER) { + return; + } + if (pname == GL::NUM_SAMPLE_COUNTS) { + *params = 2; + return; + } + if (pname == GL::SAMPLES) { + params[0] = 4; + params[1] = 8; + } } void glGetShaderPrecisionFormatMock(unsigned, unsigned, int* range, int* precision) { - range[0] = 127; - range[1] = 127; - *precision = 32; + range[0] = 127; + range[1] = 127; + *precision = 32; } /** * 用例描述: 测试OpenGL版本获取是否正确 */ PAG_TEST_F(GLUtilTest, Version_ID82986995) { - // 实参为空指针验证 - auto glVersion = GetGLVersion(nullptr); - EXPECT_EQ(glVersion.majorVersion, -1); - EXPECT_EQ(glVersion.minorVersion, -1); - // 实参为空字符串验证 - glVersion = GetGLVersion(""); - EXPECT_EQ(glVersion.majorVersion, -1); - EXPECT_EQ(glVersion.minorVersion, -1); - // 实参为多段版本号验证 - glVersion = GetGLVersion("2.1 Mesa 10.1.1"); - EXPECT_EQ(glVersion.majorVersion, 2); - EXPECT_EQ(glVersion.minorVersion, 1); - // 实参为单版本字符验证 - glVersion = GetGLVersion("3.1"); - EXPECT_EQ(glVersion.majorVersion, 3); - EXPECT_EQ(glVersion.minorVersion, 1); - // 实参为多段版本号加括号的字符串 - glVersion = GetGLVersion("OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium))"); - EXPECT_EQ(glVersion.majorVersion, 1); - EXPECT_EQ(glVersion.minorVersion, 0); - // 实参为OpenGL ES-CM - glVersion = GetGLVersion("OpenGL ES-CM 1.1 Apple A8 GPU - 50.5.1"); - EXPECT_EQ(glVersion.majorVersion, 1); - EXPECT_EQ(glVersion.minorVersion, 1); - glVersion = GetGLVersion("OpenGL ES 2.0 Apple A8 GPU - 50.5.1"); - EXPECT_EQ(glVersion.majorVersion, 2); - EXPECT_EQ(glVersion.minorVersion, 0); + // 实参为空指针验证 + auto glVersion = GetGLVersion(nullptr); + EXPECT_EQ(glVersion.majorVersion, -1); + EXPECT_EQ(glVersion.minorVersion, -1); + // 实参为空字符串验证 + glVersion = GetGLVersion(""); + EXPECT_EQ(glVersion.majorVersion, -1); + EXPECT_EQ(glVersion.minorVersion, -1); + // 实参为多段版本号验证 + glVersion = GetGLVersion("2.1 Mesa 10.1.1"); + EXPECT_EQ(glVersion.majorVersion, 2); + EXPECT_EQ(glVersion.minorVersion, 1); + // 实参为单版本字符验证 + glVersion = GetGLVersion("3.1"); + EXPECT_EQ(glVersion.majorVersion, 3); + EXPECT_EQ(glVersion.minorVersion, 1); + // 实参为多段版本号加括号的字符串 + glVersion = GetGLVersion("OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium))"); + EXPECT_EQ(glVersion.majorVersion, 1); + EXPECT_EQ(glVersion.minorVersion, 0); + // 实参为OpenGL ES-CM + glVersion = GetGLVersion("OpenGL ES-CM 1.1 Apple A8 GPU - 50.5.1"); + EXPECT_EQ(glVersion.majorVersion, 1); + EXPECT_EQ(glVersion.minorVersion, 1); + glVersion = GetGLVersion("OpenGL ES 2.0 Apple A8 GPU - 50.5.1"); + EXPECT_EQ(glVersion.majorVersion, 2); + EXPECT_EQ(glVersion.minorVersion, 0); } /** * 用例描述: 测试GLCaps */ PAG_TEST_F(GLUtilTest, Caps_ID82991749) { - { - GLInfo info(glGetStringMock, nullptr, getIntegervMock, glGetInternalformativMock, - glGetShaderPrecisionFormatMock); - GLCaps caps(info); - EXPECT_EQ(caps.vendor, vendors[i].second); - EXPECT_EQ(caps.standard, GLStandard::GL); - EXPECT_TRUE(caps.textureRedSupport); - EXPECT_TRUE(caps.multisampleDisableSupport); - EXPECT_EQ(caps.getSampleCount(5, PixelConfig::RGBA_8888), 8); - EXPECT_EQ(caps.getSampleCount(10, PixelConfig::RGBA_8888), 1); - EXPECT_EQ(caps.getSampleCount(0, PixelConfig::RGBA_8888), 1); - EXPECT_EQ(caps.getSampleCount(5, PixelConfig::ALPHA_8), 1); - } - { - ++i; - int size = static_cast(vendors.size()); - for (; i < size; ++i) { - GLInfo info(glGetStringMock, nullptr, getIntegervMock, glGetInternalformativMock, - glGetShaderPrecisionFormatMock); - GLCaps caps(info); - EXPECT_EQ(caps.vendor, vendors[i].second); + { + GLInfo info(glGetStringMock, nullptr, getIntegervMock, glGetInternalformativMock, + glGetShaderPrecisionFormatMock); + GLCaps caps(info); + EXPECT_EQ(caps.vendor, vendors[i].second); + EXPECT_EQ(caps.standard, GLStandard::GL); + EXPECT_TRUE(caps.textureRedSupport); + EXPECT_TRUE(caps.multisampleDisableSupport); + EXPECT_EQ(caps.getSampleCount(5, PixelConfig::RGBA_8888), 8); + EXPECT_EQ(caps.getSampleCount(10, PixelConfig::RGBA_8888), 1); + EXPECT_EQ(caps.getSampleCount(0, PixelConfig::RGBA_8888), 1); + EXPECT_EQ(caps.getSampleCount(5, PixelConfig::ALPHA_8), 1); + } + { + ++i; + int size = static_cast(vendors.size()); + for (; i < size; ++i) { + GLInfo info(glGetStringMock, nullptr, getIntegervMock, glGetInternalformativMock, + glGetShaderPrecisionFormatMock); + GLCaps caps(info); + EXPECT_EQ(caps.vendor, vendors[i].second); + } } - } } } // namespace pag diff --git a/test/HitTestCase.cpp b/test/HitTestCase.cpp index 5cfe1de602..82d26522fc 100644 --- a/test/HitTestCase.cpp +++ b/test/HitTestCase.cpp @@ -23,222 +23,222 @@ namespace pag { void HitTestCase::HitTestPoint(std::shared_ptr TestPAGPlayer, std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // 覆盖异常输入 - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, -1, -1, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 0, 0, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, TestPAGFile->width() * 2, - TestPAGFile->height() * 2, false)); - - // 时间轴移动到TrackMatte上 - testComposition->setCurrentTime(0.8 * 1000000); - TestPAGPlayer->flush(); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(testComposition, 250, 400, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(testComposition, 250, 600, true)); - - int target = 0; - - // 测试SolidContent - target = 0; - // 大小 720*1080 - auto solidLayer = GetLayer(testComposition, LayerType::Solid, target); - ASSERT_NE(solidLayer, nullptr); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(solidLayer, -1, -1, true)); - // Path.contains() 是闭区间,包含边界点的。而 Rect.contains() 不包含 right 和 bottom。 - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(solidLayer, 721, 1081, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(solidLayer, 0, 0, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(solidLayer, 720, 1080, true)); - - // 测试 TextContent - testComposition->setCurrentTime(5 * 1000000); - TestPAGPlayer->flush(); - target = 0; - auto textLayer = GetLayer(testComposition, LayerType::Text, target); - ASSERT_NE(textLayer, nullptr); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, -1, -1, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, 720, 1080, false)); - // 在TextLayer上,但是不在字上 - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, 70, 864, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 70, 864, false)); - // 在TextLayer上,并且在字上 - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 100, 852, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 100, 852, false)); - - // 测试ImageContent - // 坐标会被matrix remap,四舍五入时候会导致有差异,有可能接近边缘的某些像素会判断异常 - testComposition->setCurrentTime(3 * 1000000); - TestPAGPlayer->flush(); - // 大小 500*654 - target = 0; - auto imageLayer = - std::static_pointer_cast(GetLayer(testComposition, LayerType::Image, target)); - ASSERT_NE(imageLayer, nullptr); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, -1, -1, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 0, 0, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, true)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, false)); - - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, false)); - - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); - - // 测试ImageReplacement - imageLayer->replaceImage(PAGImage::FromPath("../resources/apitest/imageReplacement.png")); - TestPAGPlayer->flush(); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, -1, -1, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 0, 0, false)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, true)); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, false)); - - // 两张图片叠加的部分,同时imageLayer无像素 - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 292, 50, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 292, 50, false)); - // 两张图片叠加的部分,同时imageLayer有像素 - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, false)); - - // imageLayer无像素 - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 516, 40, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 516, 40, false)); - // imageLayer有像素 - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); - - // TODO 每种LayerContent都要写测试用例 - // TODO BitmapSequenceContent - // TODO VideoSequenceContent + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // 覆盖异常输入 + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, -1, -1, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 0, 0, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, TestPAGFile->width() * 2, + TestPAGFile->height() * 2, false)); + + // 时间轴移动到TrackMatte上 + testComposition->setCurrentTime(0.8 * 1000000); + TestPAGPlayer->flush(); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(testComposition, 250, 400, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(testComposition, 250, 600, true)); + + int target = 0; + + // 测试SolidContent + target = 0; + // 大小 720*1080 + auto solidLayer = GetLayer(testComposition, LayerType::Solid, target); + ASSERT_NE(solidLayer, nullptr); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(solidLayer, -1, -1, true)); + // Path.contains() 是闭区间,包含边界点的。而 Rect.contains() 不包含 right 和 bottom。 + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(solidLayer, 721, 1081, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(solidLayer, 0, 0, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(solidLayer, 720, 1080, true)); + + // 测试 TextContent + testComposition->setCurrentTime(5 * 1000000); + TestPAGPlayer->flush(); + target = 0; + auto textLayer = GetLayer(testComposition, LayerType::Text, target); + ASSERT_NE(textLayer, nullptr); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, -1, -1, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, 720, 1080, false)); + // 在TextLayer上,但是不在字上 + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(textLayer, 70, 864, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 70, 864, false)); + // 在TextLayer上,并且在字上 + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 100, 852, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(textLayer, 100, 852, false)); + + // 测试ImageContent + // 坐标会被matrix remap,四舍五入时候会导致有差异,有可能接近边缘的某些像素会判断异常 + testComposition->setCurrentTime(3 * 1000000); + TestPAGPlayer->flush(); + // 大小 500*654 + target = 0; + auto imageLayer = + std::static_pointer_cast(GetLayer(testComposition, LayerType::Image, target)); + ASSERT_NE(imageLayer, nullptr); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, -1, -1, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 0, 0, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, true)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, false)); + + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, false)); + + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); + + // 测试ImageReplacement + imageLayer->replaceImage(PAGImage::FromPath("../resources/apitest/imageReplacement.png")); + TestPAGPlayer->flush(); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, -1, -1, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 0, 0, false)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, true)); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 721, 1081, false)); + + // 两张图片叠加的部分,同时imageLayer无像素 + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 292, 50, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 292, 50, false)); + // 两张图片叠加的部分,同时imageLayer有像素 + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 366, 174, false)); + + // imageLayer无像素 + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(imageLayer, 516, 40, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 516, 40, false)); + // imageLayer有像素 + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(imageLayer, 424, 160, true)); + + // TODO 每种LayerContent都要写测试用例 + // TODO BitmapSequenceContent + // TODO VideoSequenceContent } void HitTestCase::VideoSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile) { - TestPAGFile->setCurrentTime(0.8 * 1000000); - TestPAGPlayer->flush(); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, false)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 600, true)); + std::shared_ptr TestPAGFile) { + TestPAGFile->setCurrentTime(0.8 * 1000000); + TestPAGPlayer->flush(); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, false)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 600, true)); } void HitTestCase::BitmapSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile) { - TestPAGFile->setCurrentTime(0.8 * 1000000); - TestPAGPlayer->flush(); - EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, true)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, false)); - EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 600, true)); + std::shared_ptr TestPAGFile) { + TestPAGFile->setCurrentTime(0.8 * 1000000); + TestPAGPlayer->flush(); + EXPECT_FALSE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, true)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 400, false)); + EXPECT_TRUE(TestPAGPlayer->hitTestPoint(TestPAGFile, 250, 600, true)); } void HitTestCase::GetLayersUnderPointEdgeCase(std::shared_ptr, - std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // 覆盖异常输入 - std::vector> results = {}; - // TODO 这里会崩溃,需要check是否这里要检查空指针 - // EXPECT_FALSE(TestPAGFile->getLayersUnderPoint(2, 2, nullptr)); - results = testComposition->getLayersUnderPoint(-1, -1); - EXPECT_EQ(static_cast(results.size()), 0); - results = testComposition->getLayersUnderPoint(0, 0); - EXPECT_EQ(static_cast(results.size()), 0); - results = - testComposition->getLayersUnderPoint(TestPAGFile->width() * 2, TestPAGFile->height() * 2); - EXPECT_EQ(static_cast(results.size()), 0); + std::shared_ptr TestPAGFile) { + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // 覆盖异常输入 + std::vector> results = {}; + // TODO 这里会崩溃,需要check是否这里要检查空指针 + // EXPECT_FALSE(TestPAGFile->getLayersUnderPoint(2, 2, nullptr)); + results = testComposition->getLayersUnderPoint(-1, -1); + EXPECT_EQ(static_cast(results.size()), 0); + results = testComposition->getLayersUnderPoint(0, 0); + EXPECT_EQ(static_cast(results.size()), 0); + results = + testComposition->getLayersUnderPoint(TestPAGFile->width() * 2, TestPAGFile->height() * 2); + EXPECT_EQ(static_cast(results.size()), 0); } void HitTestCase::GetLayersUnderPointTrackMatte(std::shared_ptr, - std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - std::vector> results = {}; - // 时间轴移动到TrackMatte上 - testComposition->setCurrentTime(0.8 * 1000000); - // 点在TrackMatte区域 - results = testComposition->getLayersUnderPoint(250, 400); - EXPECT_EQ(static_cast(results.size()), 1); - // 点在非TrackMatte区域 - results = testComposition->getLayersUnderPoint(250, 600); - EXPECT_EQ(static_cast(results.size()), 1); + std::shared_ptr TestPAGFile) { + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + std::vector> results = {}; + // 时间轴移动到TrackMatte上 + testComposition->setCurrentTime(0.8 * 1000000); + // 点在TrackMatte区域 + results = testComposition->getLayersUnderPoint(250, 400); + EXPECT_EQ(static_cast(results.size()), 1); + // 点在非TrackMatte区域 + results = testComposition->getLayersUnderPoint(250, 600); + EXPECT_EQ(static_cast(results.size()), 1); } void HitTestCase::GetLayersUnderPointImage(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - std::vector> results = {}; - // 时间轴移动到图片上 - testComposition->setCurrentTime(3 * 1000000); - TestPAGPlayer->flush(); - results = testComposition->getLayersUnderPoint(360, 200); - EXPECT_EQ(static_cast(results.size()), 3); - - results = testComposition->getLayersUnderPoint(100, 200); - EXPECT_EQ(static_cast(results.size()), 2); - - results = testComposition->getLayersUnderPoint(360, 500); - EXPECT_EQ(static_cast(results.size()), 1); + std::shared_ptr TestPAGFile) { + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + std::vector> results = {}; + // 时间轴移动到图片上 + testComposition->setCurrentTime(3 * 1000000); + TestPAGPlayer->flush(); + results = testComposition->getLayersUnderPoint(360, 200); + EXPECT_EQ(static_cast(results.size()), 3); + + results = testComposition->getLayersUnderPoint(100, 200); + EXPECT_EQ(static_cast(results.size()), 2); + + results = testComposition->getLayersUnderPoint(360, 500); + EXPECT_EQ(static_cast(results.size()), 1); } void HitTestCase::GetLayersUnderPointText(std::shared_ptr, - std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - std::vector> results = {}; - - // 时间轴移动到非文字上 - testComposition->setCurrentTime(5 * 1000000); - results = testComposition->getLayersUnderPoint(500, 500); - EXPECT_EQ(static_cast(results.size()), 1); - // 在TextLayer上,但是不在字上 - results = testComposition->getLayersUnderPoint(70, 864); - EXPECT_EQ(static_cast(results.size()), 2); - // 在TextLayer上,并且在字上 - results = testComposition->getLayersUnderPoint(100, 852); - EXPECT_EQ(static_cast(results.size()), 2); + std::shared_ptr TestPAGFile) { + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + std::vector> results = {}; + + // 时间轴移动到非文字上 + testComposition->setCurrentTime(5 * 1000000); + results = testComposition->getLayersUnderPoint(500, 500); + EXPECT_EQ(static_cast(results.size()), 1); + // 在TextLayer上,但是不在字上 + results = testComposition->getLayersUnderPoint(70, 864); + EXPECT_EQ(static_cast(results.size()), 2); + // 在TextLayer上,并且在字上 + results = testComposition->getLayersUnderPoint(100, 852); + EXPECT_EQ(static_cast(results.size()), 2); } void HitTestCase::GetLayersUnderPoint(std::shared_ptr TestPAGPlayer, std::shared_ptr TestPAGFile) { - auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // 覆盖异常输入 - std::vector> results = {}; - // TODO 这里会崩溃,需要check是否这里要检查空指针 - // EXPECT_FALSE(TestPAGFile->getLayersUnderPoint(2, 2, nullptr)); - results = testComposition->getLayersUnderPoint(-1, -1); - EXPECT_EQ(static_cast(results.size()), 0); - results = testComposition->getLayersUnderPoint(0, 0); - EXPECT_EQ(static_cast(results.size()), 0); - results = - testComposition->getLayersUnderPoint(TestPAGFile->width() * 2, TestPAGFile->height() * 2); - EXPECT_EQ(static_cast(results.size()), 0); - - // 时间轴移动到TrackMatte上 - testComposition->setCurrentTime(0.8 * 1000000); - // 点在TrackMatte区域 - results = testComposition->getLayersUnderPoint(250, 400); - EXPECT_EQ(static_cast(results.size()), 1); - // 点在非TrackMatte区域 - results = testComposition->getLayersUnderPoint(250, 600); - EXPECT_EQ(static_cast(results.size()), 1); - - // 时间轴移动到图片上 - testComposition->setCurrentTime(3 * 1000000); - TestPAGPlayer->flush(); - results = testComposition->getLayersUnderPoint(360, 200); - EXPECT_EQ(static_cast(results.size()), 3); - - results = testComposition->getLayersUnderPoint(100, 200); - EXPECT_EQ(static_cast(results.size()), 2); - - results = testComposition->getLayersUnderPoint(360, 500); - EXPECT_EQ(static_cast(results.size()), 1); - - // 时间轴移动到非文字上 - testComposition->setCurrentTime(5 * 1000000); - TestPAGPlayer->flush(); - results = testComposition->getLayersUnderPoint(500, 500); - EXPECT_EQ(static_cast(results.size()), 1); - // 在TextLayer上,但是不在字上 - results = testComposition->getLayersUnderPoint(70, 864); - EXPECT_EQ(static_cast(results.size()), 2); - // 在TextLayer上,并且在字上 - results = testComposition->getLayersUnderPoint(100, 852); - EXPECT_EQ(static_cast(results.size()), 2); + auto testComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // 覆盖异常输入 + std::vector> results = {}; + // TODO 这里会崩溃,需要check是否这里要检查空指针 + // EXPECT_FALSE(TestPAGFile->getLayersUnderPoint(2, 2, nullptr)); + results = testComposition->getLayersUnderPoint(-1, -1); + EXPECT_EQ(static_cast(results.size()), 0); + results = testComposition->getLayersUnderPoint(0, 0); + EXPECT_EQ(static_cast(results.size()), 0); + results = + testComposition->getLayersUnderPoint(TestPAGFile->width() * 2, TestPAGFile->height() * 2); + EXPECT_EQ(static_cast(results.size()), 0); + + // 时间轴移动到TrackMatte上 + testComposition->setCurrentTime(0.8 * 1000000); + // 点在TrackMatte区域 + results = testComposition->getLayersUnderPoint(250, 400); + EXPECT_EQ(static_cast(results.size()), 1); + // 点在非TrackMatte区域 + results = testComposition->getLayersUnderPoint(250, 600); + EXPECT_EQ(static_cast(results.size()), 1); + + // 时间轴移动到图片上 + testComposition->setCurrentTime(3 * 1000000); + TestPAGPlayer->flush(); + results = testComposition->getLayersUnderPoint(360, 200); + EXPECT_EQ(static_cast(results.size()), 3); + + results = testComposition->getLayersUnderPoint(100, 200); + EXPECT_EQ(static_cast(results.size()), 2); + + results = testComposition->getLayersUnderPoint(360, 500); + EXPECT_EQ(static_cast(results.size()), 1); + + // 时间轴移动到非文字上 + testComposition->setCurrentTime(5 * 1000000); + TestPAGPlayer->flush(); + results = testComposition->getLayersUnderPoint(500, 500); + EXPECT_EQ(static_cast(results.size()), 1); + // 在TextLayer上,但是不在字上 + results = testComposition->getLayersUnderPoint(70, 864); + EXPECT_EQ(static_cast(results.size()), 2); + // 在TextLayer上,并且在字上 + results = testComposition->getLayersUnderPoint(100, 852); + EXPECT_EQ(static_cast(results.size()), 2); } } // namespace pag \ No newline at end of file diff --git a/test/HitTestCase.h b/test/HitTestCase.h index 0849a25520..13e458e3b3 100644 --- a/test/HitTestCase.h +++ b/test/HitTestCase.h @@ -22,29 +22,29 @@ namespace pag { class HitTestCase { - public: - static void HitTestPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); +public: + static void HitTestPoint(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void VideoSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void VideoSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void BitmapSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void BitmapSequenceHitTestPoint(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void GetLayersUnderPointTrackMatte(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void GetLayersUnderPointTrackMatte(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void GetLayersUnderPointImage(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void GetLayersUnderPointImage(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void GetLayersUnderPointText(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void GetLayersUnderPointText(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void GetLayersUnderPointEdgeCase(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void GetLayersUnderPointEdgeCase(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); - static void GetLayersUnderPoint(std::shared_ptr TestPAGPlayer, - std::shared_ptr TestPAGFile); + static void GetLayersUnderPoint(std::shared_ptr TestPAGPlayer, + std::shared_ptr TestPAGFile); }; } // namespace pag diff --git a/test/MultiThreadCase.cpp b/test/MultiThreadCase.cpp index bee1ce7100..833d2cc1e5 100644 --- a/test/MultiThreadCase.cpp +++ b/test/MultiThreadCase.cpp @@ -30,87 +30,87 @@ PAG_TEST_CASE(MultiThreadCase) * swiftshader在多线程同时创建 EGLContextExt 时候会失败,需加锁 */ void mockPAGView() { - auto file = PAGFile::Load(DEFAULT_PAG_PATH); - ASSERT_NE(file, nullptr) << "pag path is:" << DEFAULT_PAG_PATH << std::endl; - auto surface = PAGSurface::MakeOffscreen(file->width(), file->height()); - auto player = std::make_shared(); - player->setSurface(surface); - surface->drawable->getDevice(); - ASSERT_NE(surface, nullptr); - player->setComposition(file); - int num = 20; - for (int i = 0; i < num; i++) { - long time = file->duration() * i / num; - file->setCurrentTime(time); - player->flush(); - DumpMD5(surface); - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } + auto file = PAGFile::Load(DEFAULT_PAG_PATH); + ASSERT_NE(file, nullptr) << "pag path is:" << DEFAULT_PAG_PATH << std::endl; + auto surface = PAGSurface::MakeOffscreen(file->width(), file->height()); + auto player = std::make_shared(); + player->setSurface(surface); + surface->drawable->getDevice(); + ASSERT_NE(surface, nullptr); + player->setComposition(file); + int num = 20; + for (int i = 0; i < num; i++) { + long time = file->duration() * i / num; + file->setCurrentTime(time); + player->flush(); + DumpMD5(surface); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } } /** * 用例描述: 使用多个PAGPlayer模拟多个PAGView同时渲染 */ PAG_TEST(SimpleMultiThreadCase, MultiPAGView) { - std::vector threads; - int num = 10; - for (int i = 0; i < num; i++) { - threads.emplace_back(std::thread(mockPAGView)); - } - for (auto& mock : threads) { - if (mock.joinable()) mock.join(); - } + std::vector threads; + int num = 10; + for (int i = 0; i < num; i++) { + threads.emplace_back(std::thread(mockPAGView)); + } + for (auto& mock : threads) { + if (mock.joinable()) mock.join(); + } } void mockAsyncFlush(int num = 30) { - ASSERT_NE(PAGCpuTest::TestPAGSurface, nullptr); - for (int i = 0; i < num; i++) { - PAGCpuTest::TestPAGFile->setCurrentTime(PAGCpuTest::TestPAGFile->duration() * i / num); - PAGCpuTest::TestPAGPlayer->flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - std::cout << "\nmockAsyncFlush finish" << std::endl; + ASSERT_NE(PAGCpuTest::TestPAGSurface, nullptr); + for (int i = 0; i < num; i++) { + PAGCpuTest::TestPAGFile->setCurrentTime(PAGCpuTest::TestPAGFile->duration() * i / num); + PAGCpuTest::TestPAGPlayer->flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + std::cout << "\nmockAsyncFlush finish" << std::endl; } /** * 用例描述: 测试在A线程调用flush,B线程同时进行编辑操作 */ PAG_TEST_F(MultiThreadCase, AsyncFlush) { - auto mockThread = std::thread(mockAsyncFlush, 10); - std::shared_ptr pagCom = - std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - ASSERT_NE(pagCom, nullptr); + auto mockThread = std::thread(mockAsyncFlush, 10); + std::shared_ptr pagCom = + std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + ASSERT_NE(pagCom, nullptr); - for (int i = 0; i < 10; i++) { - pagCom->swapLayerAt(2, 3); - PAGCpuTest::TestPAGPlayer->flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - auto layer = pagCom->getLayerAt(2); - PAGCpuTest::TestPAGPlayer->flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - pagCom->removeLayerAt(2); - PAGCpuTest::TestPAGPlayer->flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - pagCom->addLayerAt(layer, 2); - PAGCpuTest::TestPAGPlayer->flush(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - std::cout << "\nAsyncFlush edit" << std::endl; - mockThread.join(); + for (int i = 0; i < 10; i++) { + pagCom->swapLayerAt(2, 3); + PAGCpuTest::TestPAGPlayer->flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + auto layer = pagCom->getLayerAt(2); + PAGCpuTest::TestPAGPlayer->flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + pagCom->removeLayerAt(2); + PAGCpuTest::TestPAGPlayer->flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + pagCom->addLayerAt(layer, 2); + PAGCpuTest::TestPAGPlayer->flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + std::cout << "\nAsyncFlush edit" << std::endl; + mockThread.join(); } /** * 用例描述: 测试在A线程调用flush,B线程进行freeCache */ PAG_TEST_F(MultiThreadCase, AsyncFlushAndFreeCache) { - ASSERT_NE(TestPAGFile, nullptr); - auto mockThread = std::thread(mockAsyncFlush, 200); - for (int i = 0; i < 200; i++) { - PAGCpuTest::TestPAGSurface->freeCache(); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } - std::cout << "\nAsyncFlush edit" << std::endl; - mockThread.join(); + ASSERT_NE(TestPAGFile, nullptr); + auto mockThread = std::thread(mockAsyncFlush, 200); + for (int i = 0; i < 200; i++) { + PAGCpuTest::TestPAGSurface->freeCache(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + } + std::cout << "\nAsyncFlush edit" << std::endl; + mockThread.join(); } /** @@ -118,22 +118,22 @@ PAG_TEST_F(MultiThreadCase, AsyncFlushAndFreeCache) { * 多线程会不会引起死锁之类的问题,正确性是HitTest接口本身来保证 */ PAG_TEST_F(MultiThreadCase, HitTestPoint) { - auto mockThread = std::thread(mockAsyncFlush, 30); - for (int i = 0; i < 15; i++) { - TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); - } - mockThread.join(); + auto mockThread = std::thread(mockAsyncFlush, 30); + for (int i = 0; i < 15; i++) { + TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); + } + mockThread.join(); } /** * 用例描述: GetLayersUnderPoint功能测试 */ PAG_TEST_F(MultiThreadCase, GetLayersUnderPoint) { - auto mockThread = std::thread(mockAsyncFlush, 30); - for (int i = 0; i < 30; i++) { - TestPAGFile->getLayersUnderPoint(720.0 * i / 15, 1080.0 * i / 15); - } - mockThread.join(); + auto mockThread = std::thread(mockAsyncFlush, 30); + for (int i = 0; i < 30; i++) { + TestPAGFile->getLayersUnderPoint(720.0 * i / 15, 1080.0 * i / 15); + } + mockThread.join(); } PAG_TEST_CASE(MultiThreadCase_BitmapSequenceHitTest) @@ -142,11 +142,11 @@ PAG_TEST_CASE(MultiThreadCase_BitmapSequenceHitTest) * 用例描述: 图片序列帧的hitTest" */ PAG_TEST_F(MultiThreadCase_BitmapSequenceHitTest, BitmapSequenceHitTestPoint) { - auto mockThread = std::thread(mockAsyncFlush, 30); - for (int i = 0; i < 30; i++) { - TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); - } - mockThread.join(); + auto mockThread = std::thread(mockAsyncFlush, 30); + for (int i = 0; i < 30; i++) { + TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); + } + mockThread.join(); } PAG_TEST_CASE(MultiThreadCase_VideoSequenceHitTest) @@ -155,10 +155,10 @@ PAG_TEST_CASE(MultiThreadCase_VideoSequenceHitTest) * 用例描述: 视频序列帧的hitTest */ PAG_TEST_F(MultiThreadCase_VideoSequenceHitTest, VideoSequenceHitTestPoint) { - auto mockThread = std::thread(mockAsyncFlush, 30); - for (int i = 0; i < 30; i++) { - TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); - } - mockThread.join(); + auto mockThread = std::thread(mockAsyncFlush, 30); + for (int i = 0; i < 30; i++) { + TestPAGPlayer->hitTestPoint(TestPAGFile, 720.0 * i / 15, 1080.0 * i / 15, true); + } + mockThread.join(); } } // namespace pag diff --git a/test/PAGBlendTest.cpp b/test/PAGBlendTest.cpp index 1747a32598..a172323a74 100644 --- a/test/PAGBlendTest.cpp +++ b/test/PAGBlendTest.cpp @@ -30,176 +30,176 @@ PAG_TEST_CASE(PAGBlendTest) * 用例描述: 测试基础混合模式 */ PAG_TEST_F(PAGBlendTest, Blend_ID83348933) { - std::vector files; - GetAllPAGFiles("../resources/blend", files); - auto pagSurface = PAGSurface::MakeOffscreen(400, 400); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - for (auto& file : files) { - auto pagFile = PAGFile::Load(file); - EXPECT_NE(pagFile, nullptr); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.5); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - auto found = file.find_last_of("/\\"); - auto fileName = file.substr(found + 1); - PAGTestEnvironment::DumpJson["PAGBlendTest"]["base"][fileName] = md5; + std::vector files; + GetAllPAGFiles("../resources/blend", files); + auto pagSurface = PAGSurface::MakeOffscreen(400, 400); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + for (auto& file : files) { + auto pagFile = PAGFile::Load(file); + EXPECT_NE(pagFile, nullptr); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.5); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + auto found = file.find_last_of("/\\"); + auto fileName = file.substr(found + 1); + PAGTestEnvironment::DumpJson["PAGBlendTest"]["base"][fileName] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["base"][fileName]; - auto path = "../test/out/blend_" + fileName + ".png"; - TraceIf(pagSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["base"][fileName]; + auto path = "../test/out/blend_" + fileName + ".png"; + TraceIf(pagSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - } + } } GLTextureInfo GetBottomLeftImage(std::shared_ptr device, int width, int height) { - auto context = device->lockContext(); - auto gl = GLContext::Unwrap(context); - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto surface = - PAGSurface::MakeFrom(BackendTexture(textureInfo, width, height), ImageOrigin::BottomLeft); - device->unlock(); - auto composition = PAGComposition::Make(1080, 1920); - auto imageLayer = PAGImageLayer::Make(1080, 1920, 1000000); - imageLayer->replaceImage(PAGImage::FromPath("../assets/mountain.jpg")); - composition->addLayer(imageLayer); - auto player = std::make_shared(); - player->setSurface(surface); - player->setComposition(composition); - player->flush(); - return textureInfo; + auto context = device->lockContext(); + auto gl = GLContext::Unwrap(context); + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto surface = + PAGSurface::MakeFrom(BackendTexture(textureInfo, width, height), ImageOrigin::BottomLeft); + device->unlock(); + auto composition = PAGComposition::Make(1080, 1920); + auto imageLayer = PAGImageLayer::Make(1080, 1920, 1000000); + imageLayer->replaceImage(PAGImage::FromPath("../assets/mountain.jpg")); + composition->addLayer(imageLayer); + auto player = std::make_shared(); + player->setSurface(surface); + player->setComposition(composition); + player->flush(); + return textureInfo; } /** * 用例描述: 使用blend时,如果当前的frameBuffer是BottomLeft的,复制逻辑验证 */ PAG_TEST_F(PAGBlendTest, CopyDstTexture_ID83384135) { - auto width = 400; - auto height = 400; - auto device = NativeGLDevice::Make(); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto gl = GLContext::Unwrap(context); - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto backendTexture = BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); - device->unlock(); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - auto pagFile = PAGFile::Load("../resources/blend/Multiply.pag"); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.5); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGBlendTest"]["CopyDstTexture_ID83384135"] = md5; + auto width = 400; + auto height = 400; + auto device = NativeGLDevice::Make(); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto gl = GLContext::Unwrap(context); + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto backendTexture = BackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); + device->unlock(); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + auto pagFile = PAGFile::Load("../resources/blend/Multiply.pag"); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.5); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGBlendTest"]["CopyDstTexture_ID83384135"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["CopyDstTexture_ID83384135"]; - auto path = "../test/out/blend_Multiply_CopyDstTexture.png"; - TraceIf(pagSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["CopyDstTexture_ID83384135"]; + auto path = "../test/out/blend_Multiply_CopyDstTexture.png"; + TraceIf(pagSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - context = device->lockContext(); - gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &textureInfo.id); - device->unlock(); + context = device->lockContext(); + gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &textureInfo.id); + device->unlock(); } /** * 用例描述: 替换的texture是BottomLeft,renderTarget是TopLeft */ PAG_TEST_F(PAGBlendTest, TextureBottomLeft_ID83721303) { - auto width = 720; - auto height = 1280; - auto device = NativeGLDevice::Make(); - auto replaceTextureInfo = GetBottomLeftImage(device, width, height); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto gl = GLContext::Unwrap(context); - auto replaceImage = PAGImage::FromTexture(BackendTexture(replaceTextureInfo, width, height), - ImageOrigin::BottomLeft); - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto backendTexture = BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); - device->unlock(); + auto width = 720; + auto height = 1280; + auto device = NativeGLDevice::Make(); + auto replaceTextureInfo = GetBottomLeftImage(device, width, height); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto gl = GLContext::Unwrap(context); + auto replaceImage = PAGImage::FromTexture(BackendTexture(replaceTextureInfo, width, height), + ImageOrigin::BottomLeft); + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto backendTexture = BackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); + device->unlock(); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - auto pagFile = PAGFile::Load("../resources/apitest/texture_bottom_left.pag"); - pagFile->replaceImage(3, replaceImage); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.34); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGBlendTest"]["TextureBottomLeft_ID83721303"] = md5; + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + auto pagFile = PAGFile::Load("../resources/apitest/texture_bottom_left.pag"); + pagFile->replaceImage(3, replaceImage); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.34); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGBlendTest"]["TextureBottomLeft_ID83721303"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["TextureBottomLeft_ID83721303"]; - auto path = "../test/out/TextureBottomLeft_ID83721303.png"; - TraceIf(pagSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["TextureBottomLeft_ID83721303"]; + auto path = "../test/out/TextureBottomLeft_ID83721303.png"; + TraceIf(pagSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - context = device->lockContext(); - gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &replaceTextureInfo.id); - gl->deleteTextures(1, &textureInfo.id); - device->unlock(); + context = device->lockContext(); + gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &replaceTextureInfo.id); + gl->deleteTextures(1, &textureInfo.id); + device->unlock(); } /** * 用例描述: 替换的texture和renderTarget都是BottomLeft */ PAG_TEST_F(PAGBlendTest, BothBottomLeft_ID83721689) { - auto width = 720; - auto height = 1280; - auto device = NativeGLDevice::Make(); - auto replaceTextureInfo = GetBottomLeftImage(device, width, height); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto replaceImage = PAGImage::FromTexture( - BackendTexture(replaceTextureInfo, width / 2, height / 2), ImageOrigin::BottomLeft); - replaceImage->setMatrix( - Matrix::MakeTrans(static_cast(width) * 0.1, static_cast(height) * 0.2)); - auto gl = GLContext::Unwrap(context); - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto backendTexture = BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); - device->unlock(); + auto width = 720; + auto height = 1280; + auto device = NativeGLDevice::Make(); + auto replaceTextureInfo = GetBottomLeftImage(device, width, height); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto replaceImage = PAGImage::FromTexture( + BackendTexture(replaceTextureInfo, width / 2, height / 2), ImageOrigin::BottomLeft); + replaceImage->setMatrix( + Matrix::MakeTrans(static_cast(width) * 0.1, static_cast(height) * 0.2)); + auto gl = GLContext::Unwrap(context); + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto backendTexture = BackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); + device->unlock(); - auto composition = PAGComposition::Make(width, height); - auto imageLayer = PAGImageLayer::Make(width, height, 1000000); - imageLayer->replaceImage(replaceImage); - composition->addLayer(imageLayer); + auto composition = PAGComposition::Make(width, height); + auto imageLayer = PAGImageLayer::Make(width, height, 1000000); + imageLayer->replaceImage(replaceImage); + composition->addLayer(imageLayer); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(composition); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.3); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGBlendTest"]["BothBottomLeft_ID83721689"] = md5; + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(composition); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.3); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGBlendTest"]["BothBottomLeft_ID83721689"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["BothBottomLeft_ID83721689"]; - auto path = "../test/out/BothBottomLeft_ID83721689.png"; - TraceIf(pagSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGBlendTest"]["BothBottomLeft_ID83721689"]; + auto path = "../test/out/BothBottomLeft_ID83721689.png"; + TraceIf(pagSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &replaceTextureInfo.id); - gl->deleteTextures(1, &textureInfo.id); - device->unlock(); + context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &replaceTextureInfo.id); + gl->deleteTextures(1, &textureInfo.id); + device->unlock(); } } // namespace pag diff --git a/test/PAGCompositionTest.cpp b/test/PAGCompositionTest.cpp index f5eb4ab2db..0111cf1d96 100644 --- a/test/PAGCompositionTest.cpp +++ b/test/PAGCompositionTest.cpp @@ -30,75 +30,78 @@ PAG_TEST_SUIT(PAGCompositionTest) * 用例描述: PAGCompositionLayer基础功能 */ PAG_TEST_F(PAGCompositionTest, composition) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - ASSERT_EQ(pagComposition->width(), 720); - ASSERT_EQ(pagComposition->height(), 1080); - ASSERT_EQ(pagComposition->numChildren(), 6); - pagComposition->setCurrentTime(3 * 1000000); - pagComposition->setContentSize(540, 960); - TestPAGPlayer->flush(); - - auto imageLayer1 = std::static_pointer_cast(pagComposition->getLayerAt(2)); - ASSERT_NE(imageLayer1, nullptr); - ASSERT_EQ(imageLayer1->layerName(), "PAGImageLayer1"); - ASSERT_EQ(pagComposition->getLayerIndex(imageLayer1), 2); - ASSERT_TRUE(pagComposition->contains(imageLayer1)); - - auto imageLayer2 = std::static_pointer_cast(pagComposition->getLayerAt(3)); - ASSERT_NE(imageLayer2, nullptr); - ASSERT_EQ(imageLayer2->layerName(), "PAGImageLayer2"); - - pagComposition->swapLayer(imageLayer1, imageLayer2); - TestPAGPlayer->flush(); - auto swapLayerMd5 = getMd5FromSnap(); - - pagComposition->swapLayerAt(2, 3); - TestPAGPlayer->flush(); - auto swapLayerAtMd5 = getMd5FromSnap(); - - pagComposition->setLayerIndex(imageLayer1, 3); - TestPAGPlayer->flush(); - auto setLayerIndexMd5 = getMd5FromSnap(); - - pagComposition->removeLayer(imageLayer1); - TestPAGPlayer->flush(); - auto removeLayerMd5 = getMd5FromSnap(); - - pagComposition->removeLayerAt(2); - TestPAGPlayer->flush(); - auto removeLayerAtMd5 = getMd5FromSnap(); - - pagComposition->removeAllLayers(); - TestPAGPlayer->flush(); - auto removeAllLayersMd5 = getMd5FromSnap(); - - auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); - auto pagComposition2 = std::static_pointer_cast(pagFile2->getLayerAt(0)); - auto imageLayer = pagComposition2->getLayerAt(2); - pagComposition->addLayer(imageLayer); - TestPAGPlayer->flush(); - auto addLayerMd5 = getMd5FromSnap(); - - pagComposition->addLayerAt(pagComposition2->getLayerAt(3), 0); - TestPAGPlayer->flush(); - auto addLayerAtMd5 = DumpMD5(TestPAGSurface); - - pagComposition->setContentSize(300, 300); - ASSERT_EQ(pagComposition->width(), 300); - ASSERT_EQ(pagComposition->height(), 300); - TestPAGPlayer->flush(); - auto changeContentSizeMd5 = DumpMD5(TestPAGSurface); - - json out = {{"composition", - {{"swapLayer", swapLayerMd5}, + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + ASSERT_EQ(pagComposition->width(), 720); + ASSERT_EQ(pagComposition->height(), 1080); + ASSERT_EQ(pagComposition->numChildren(), 6); + pagComposition->setCurrentTime(3 * 1000000); + pagComposition->setContentSize(540, 960); + TestPAGPlayer->flush(); + + auto imageLayer1 = std::static_pointer_cast(pagComposition->getLayerAt(2)); + ASSERT_NE(imageLayer1, nullptr); + ASSERT_EQ(imageLayer1->layerName(), "PAGImageLayer1"); + ASSERT_EQ(pagComposition->getLayerIndex(imageLayer1), 2); + ASSERT_TRUE(pagComposition->contains(imageLayer1)); + + auto imageLayer2 = std::static_pointer_cast(pagComposition->getLayerAt(3)); + ASSERT_NE(imageLayer2, nullptr); + ASSERT_EQ(imageLayer2->layerName(), "PAGImageLayer2"); + + pagComposition->swapLayer(imageLayer1, imageLayer2); + TestPAGPlayer->flush(); + auto swapLayerMd5 = getMd5FromSnap(); + + pagComposition->swapLayerAt(2, 3); + TestPAGPlayer->flush(); + auto swapLayerAtMd5 = getMd5FromSnap(); + + pagComposition->setLayerIndex(imageLayer1, 3); + TestPAGPlayer->flush(); + auto setLayerIndexMd5 = getMd5FromSnap(); + + pagComposition->removeLayer(imageLayer1); + TestPAGPlayer->flush(); + auto removeLayerMd5 = getMd5FromSnap(); + + pagComposition->removeLayerAt(2); + TestPAGPlayer->flush(); + auto removeLayerAtMd5 = getMd5FromSnap(); + + pagComposition->removeAllLayers(); + TestPAGPlayer->flush(); + auto removeAllLayersMd5 = getMd5FromSnap(); + + auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); + auto pagComposition2 = std::static_pointer_cast(pagFile2->getLayerAt(0)); + auto imageLayer = pagComposition2->getLayerAt(2); + pagComposition->addLayer(imageLayer); + TestPAGPlayer->flush(); + auto addLayerMd5 = getMd5FromSnap(); + + pagComposition->addLayerAt(pagComposition2->getLayerAt(3), 0); + TestPAGPlayer->flush(); + auto addLayerAtMd5 = DumpMD5(TestPAGSurface); + + pagComposition->setContentSize(300, 300); + ASSERT_EQ(pagComposition->width(), 300); + ASSERT_EQ(pagComposition->height(), 300); + TestPAGPlayer->flush(); + auto changeContentSizeMd5 = DumpMD5(TestPAGSurface); + + json out = {{"composition", + { {"swapLayer", swapLayerMd5}, {"setLayerIndexMd5", setLayerIndexMd5}, {"removeLayerMd5", removeLayerMd5}, {"removeLayerAtMd5", removeLayerAtMd5}, {"removeAllLayersMd5", removeAllLayersMd5}, {"addLayerMd5", addLayerMd5}, {"addLayerAtMd5", addLayerAtMd5}, - {"changeContentSizeMd5", changeContentSizeMd5}}}}; - PAGTestEnvironment::DumpJson["PAGCompositionTest"] = out; + {"changeContentSizeMd5", changeContentSizeMd5} + } + } + }; + PAGTestEnvironment::DumpJson["PAGCompositionTest"] = out; } PAG_TEST_SUIT_WITH_PATH(VideoSequenceSize, "../resources/apitest/video_sequence_size.pag") @@ -107,17 +110,17 @@ PAG_TEST_SUIT_WITH_PATH(VideoSequenceSize, "../resources/apitest/video_sequence_ * 用例描述: VideoSequence的大小和Composition不一致 */ PAG_TEST_F(VideoSequenceSize, VideoSequence_ID82854769) { - TestPAGFile->setMatrix(Matrix::MakeScale(0.8625)); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto image = MakeSnapshot(TestPAGSurface); - auto md5 = DumpMD5(image); - PAGTestEnvironment::DumpJson["PAGCompositionTest"]["VideoSequence_ID82854769"] = md5; + TestPAGFile->setMatrix(Matrix::MakeScale(0.8625)); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto image = MakeSnapshot(TestPAGSurface); + auto md5 = DumpMD5(image); + PAGTestEnvironment::DumpJson["PAGCompositionTest"]["VideoSequence_ID82854769"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = - PAGTestEnvironment::CompareJson["PAGCompositionTest"]["VideoSequence_ID82854769"]; - TraceIf(image, "../test/out/VideoSequence_ID82854769.png", compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = + PAGTestEnvironment::CompareJson["PAGCompositionTest"]["VideoSequence_ID82854769"]; + TraceIf(image, "../test/out/VideoSequence_ID82854769.png", compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif } @@ -128,319 +131,319 @@ PAG_TEST_CASE(ContainerTest) * 用例描述: PAGCompositionLayer getLayerAt */ PAG_TEST_F(ContainerTest, getLayerAt) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - - // case 0: 合法索引 - auto pagLayer = pagComposition->getLayerAt(0); - auto pagLayer2 = pagLayer->parent()->getLayerAt(0); - EXPECT_EQ(pagLayer, pagLayer2); - - // Case 1: index < 0 - pagLayer = pagComposition->getLayerAt(-1); - EXPECT_EQ(pagLayer, nullptr); - - // Case 2: index >= layers总数 - pagLayer = pagComposition->getLayerAt(pagComposition->numChildren()); - EXPECT_EQ(pagLayer, nullptr); - - // case 3: 当前PAGComposition是空/等同于索引越界 - auto emptyPAGComposition = PAGComposition::Make(100, 100); - auto emptyPagLayer = emptyPAGComposition->getLayerAt(0); - EXPECT_EQ(emptyPagLayer, nullptr); - - // case 4: 通过Make创建空容器 - emptyPAGComposition = PAGComposition::Make(100, 100); - emptyPagLayer = emptyPAGComposition->getLayerAt(0); - EXPECT_EQ(emptyPagLayer, nullptr); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + + // case 0: 合法索引 + auto pagLayer = pagComposition->getLayerAt(0); + auto pagLayer2 = pagLayer->parent()->getLayerAt(0); + EXPECT_EQ(pagLayer, pagLayer2); + + // Case 1: index < 0 + pagLayer = pagComposition->getLayerAt(-1); + EXPECT_EQ(pagLayer, nullptr); + + // Case 2: index >= layers总数 + pagLayer = pagComposition->getLayerAt(pagComposition->numChildren()); + EXPECT_EQ(pagLayer, nullptr); + + // case 3: 当前PAGComposition是空/等同于索引越界 + auto emptyPAGComposition = PAGComposition::Make(100, 100); + auto emptyPagLayer = emptyPAGComposition->getLayerAt(0); + EXPECT_EQ(emptyPagLayer, nullptr); + + // case 4: 通过Make创建空容器 + emptyPAGComposition = PAGComposition::Make(100, 100); + emptyPagLayer = emptyPAGComposition->getLayerAt(0); + EXPECT_EQ(emptyPagLayer, nullptr); } /** * 用例描述: PAGCompositionLayer getLayerIndex */ PAG_TEST_F(ContainerTest, getLayerIndex) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: pagLayer 是当前PAGComposition的子Layer - auto pagLayer = pagComposition->getLayerAt(1); - auto index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 1); + // case 0: pagLayer 是当前PAGComposition的子Layer + auto pagLayer = pagComposition->getLayerAt(1); + auto index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 1); - // case 1: pagLayer = nullptr - index = pagComposition->getLayerIndex(nullptr); - EXPECT_LT(index, 0); + // case 1: pagLayer = nullptr + index = pagComposition->getLayerIndex(nullptr); + EXPECT_LT(index, 0); - // case 2: pagLayer指向另外一个PAGComposition的Layer - auto pagFile = PAGFile::Load(GetPagPath()); - auto pagLayer2 = pagFile->getLayerAt(0); + // case 2: pagLayer指向另外一个PAGComposition的Layer + auto pagFile = PAGFile::Load(GetPagPath()); + auto pagLayer2 = pagFile->getLayerAt(0); - index = pagComposition->getLayerIndex(pagLayer2); - EXPECT_LT(index, 0); + index = pagComposition->getLayerIndex(pagLayer2); + EXPECT_LT(index, 0); - // case 3: 当前PAGComposition是空 - auto emptyPAGComposition = PAGComposition::Make(100, 100); - index = emptyPAGComposition->getLayerIndex(pagLayer); - EXPECT_LT(index, 0); + // case 3: 当前PAGComposition是空 + auto emptyPAGComposition = PAGComposition::Make(100, 100); + index = emptyPAGComposition->getLayerIndex(pagLayer); + EXPECT_LT(index, 0); } /** * 用例描述: ContainerTest setLayerIndex */ PAG_TEST_F(ContainerTest, setLayerIndex) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 - auto pagLayer = pagComposition->getLayerAt(1); - pagComposition->setLayerIndex(pagLayer, 0); - auto layerIndex = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(layerIndex, 0); - - // case 1: 当前PAGComposition是空 - auto emptyPAGComposition = PAGComposition::Make(100, 100); - emptyPAGComposition->setLayerIndex(pagLayer, 0); - EXPECT_EQ(pagLayer->parent() == emptyPAGComposition, false); - - // case 2: 当前pagLayer不是当前PAGComposition的子Layer - auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); - pagComposition->setLayerIndex(emptyPAGLayer, 0); - auto index = pagComposition->getLayerIndex(emptyPAGLayer); - EXPECT_LT(index, 0); - - auto count = pagComposition->numChildren(); - // case 3: index <0 - pagComposition->setLayerIndex(pagLayer, -1); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, count - 1); - - // case 4: index 超出layers数组范围 - count = pagComposition->numChildren(); - pagComposition->setLayerIndex(pagLayer, count); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, count - 1); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 + auto pagLayer = pagComposition->getLayerAt(1); + pagComposition->setLayerIndex(pagLayer, 0); + auto layerIndex = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(layerIndex, 0); + + // case 1: 当前PAGComposition是空 + auto emptyPAGComposition = PAGComposition::Make(100, 100); + emptyPAGComposition->setLayerIndex(pagLayer, 0); + EXPECT_EQ(pagLayer->parent() == emptyPAGComposition, false); + + // case 2: 当前pagLayer不是当前PAGComposition的子Layer + auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); + pagComposition->setLayerIndex(emptyPAGLayer, 0); + auto index = pagComposition->getLayerIndex(emptyPAGLayer); + EXPECT_LT(index, 0); + + auto count = pagComposition->numChildren(); + // case 3: index <0 + pagComposition->setLayerIndex(pagLayer, -1); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, count - 1); + + // case 4: index 超出layers数组范围 + count = pagComposition->numChildren(); + pagComposition->setLayerIndex(pagLayer, count); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, count - 1); } /** * 用例描述: ContainerTest addLayer */ PAG_TEST_F(ContainerTest, addLayer) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 参数pagLayer是另外一个PAGComposition的子Layer - auto pagFile = PAGFile::Load(getPagPath()); - auto addLayer = pagFile->getLayerAt(0); - pagComposition->addLayer(addLayer); - EXPECT_EQ(addLayer->parent() == pagComposition, true); - EXPECT_EQ(pagComposition->contains(addLayer), true); - - // case 1: 参数pagLayer = nullptr - auto result = pagComposition->addLayer(nullptr); - EXPECT_EQ(result, false); - - // case 2: 参数pagLayer是当前PAGComposition的子layer,相当于调整顺序 - auto count = pagComposition->numChildren(); - auto pagLayer = pagComposition->getLayerAt(0); - pagComposition->addLayer(pagLayer); - auto index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, count - 1); - - // case 3: 参数pagLayer是当前PAGComposition或者是当前PAGComposition的父亲节点 - EXPECT_FALSE(pagComposition->addLayer(pagComposition)); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 参数pagLayer是另外一个PAGComposition的子Layer + auto pagFile = PAGFile::Load(getPagPath()); + auto addLayer = pagFile->getLayerAt(0); + pagComposition->addLayer(addLayer); + EXPECT_EQ(addLayer->parent() == pagComposition, true); + EXPECT_EQ(pagComposition->contains(addLayer), true); + + // case 1: 参数pagLayer = nullptr + auto result = pagComposition->addLayer(nullptr); + EXPECT_EQ(result, false); + + // case 2: 参数pagLayer是当前PAGComposition的子layer,相当于调整顺序 + auto count = pagComposition->numChildren(); + auto pagLayer = pagComposition->getLayerAt(0); + pagComposition->addLayer(pagLayer); + auto index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, count - 1); + + // case 3: 参数pagLayer是当前PAGComposition或者是当前PAGComposition的父亲节点 + EXPECT_FALSE(pagComposition->addLayer(pagComposition)); } /** * 用例描述: ContainerTest addLayerAt */ PAG_TEST_F(ContainerTest, addLayerAt) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - - auto pagFile = PAGFile::Load(getPagPath()); - auto targetLayer = pagFile->getLayerAt(0); - pagComposition->addLayer(targetLayer); - - // case 0: 正常情况 - auto result = pagComposition->addLayerAt(targetLayer, 1); - EXPECT_EQ(result, true); - EXPECT_EQ(targetLayer->parent() == pagComposition, true); - EXPECT_EQ(pagComposition->contains(targetLayer), true); - EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), 1); - - pagComposition->removeLayer(targetLayer); - // case 1: index <0 - auto count = pagComposition->numChildren(); - EXPECT_TRUE(pagComposition->addLayerAt(targetLayer, -1)); - EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), count); - - // case 2: index超出范围,添加当前Composition下的layer会导致位置重排 - count = pagComposition->numChildren(); - EXPECT_TRUE(pagComposition->addLayerAt(targetLayer, count)); - EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), pagComposition->numChildren() - 1); - //剩余测试和 addLayer一样 + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + + auto pagFile = PAGFile::Load(getPagPath()); + auto targetLayer = pagFile->getLayerAt(0); + pagComposition->addLayer(targetLayer); + + // case 0: 正常情况 + auto result = pagComposition->addLayerAt(targetLayer, 1); + EXPECT_EQ(result, true); + EXPECT_EQ(targetLayer->parent() == pagComposition, true); + EXPECT_EQ(pagComposition->contains(targetLayer), true); + EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), 1); + + pagComposition->removeLayer(targetLayer); + // case 1: index <0 + auto count = pagComposition->numChildren(); + EXPECT_TRUE(pagComposition->addLayerAt(targetLayer, -1)); + EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), count); + + // case 2: index超出范围,添加当前Composition下的layer会导致位置重排 + count = pagComposition->numChildren(); + EXPECT_TRUE(pagComposition->addLayerAt(targetLayer, count)); + EXPECT_EQ(pagComposition->getLayerIndex(targetLayer), pagComposition->numChildren() - 1); + //剩余测试和 addLayer一样 } /** * 用例描述: ContainerTest contains */ PAG_TEST_F(ContainerTest, contains) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 - auto pagLayer = pagComposition->getLayerAt(0); - auto result = pagComposition->contains(pagLayer); - EXPECT_EQ(result, true); - - // case 1: 参数pagLayer 为空 - EXPECT_FALSE(pagComposition->contains(nullptr)); - - // case 2: 当前PAGComposition为空 - auto emptyPAGComposition = PAGComposition::Make(100, 100); - result = emptyPAGComposition->contains(pagLayer); - EXPECT_EQ(result, false); - - // case 3: PAGLayer是另外一个PAGComposition的 - auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); - result = pagComposition->contains(emptyPAGLayer); - EXPECT_EQ(result, false); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 + auto pagLayer = pagComposition->getLayerAt(0); + auto result = pagComposition->contains(pagLayer); + EXPECT_EQ(result, true); + + // case 1: 参数pagLayer 为空 + EXPECT_FALSE(pagComposition->contains(nullptr)); + + // case 2: 当前PAGComposition为空 + auto emptyPAGComposition = PAGComposition::Make(100, 100); + result = emptyPAGComposition->contains(pagLayer); + EXPECT_EQ(result, false); + + // case 3: PAGLayer是另外一个PAGComposition的 + auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); + result = pagComposition->contains(emptyPAGLayer); + EXPECT_EQ(result, false); } /** * 用例描述: ContainerTest removeLayer */ PAG_TEST_F(ContainerTest, removeLayer) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 - auto pagLayer = pagComposition->getLayerAt(0); - EXPECT_EQ(pagLayer->parent(), pagComposition); - auto result = pagComposition->removeLayer(pagLayer); - EXPECT_EQ(pagLayer->parent(), nullptr); - EXPECT_EQ(result == pagLayer, true); - auto check = pagComposition->contains(pagLayer); - EXPECT_EQ(check, false); - - // case 1: 传入nullptr参数 - result = pagComposition->removeLayer(nullptr); - EXPECT_EQ(result == nullptr, true); - - // case 2: pagLayer不属于当前PAGComposition - auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); - result = pagComposition->removeLayer(emptyPAGLayer); - EXPECT_EQ(result == nullptr, true); - - // case 3: PAGLayer是当前PAGComposition - result = pagComposition->removeLayer(pagComposition); - EXPECT_EQ(result == nullptr, true); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 + auto pagLayer = pagComposition->getLayerAt(0); + EXPECT_EQ(pagLayer->parent(), pagComposition); + auto result = pagComposition->removeLayer(pagLayer); + EXPECT_EQ(pagLayer->parent(), nullptr); + EXPECT_EQ(result == pagLayer, true); + auto check = pagComposition->contains(pagLayer); + EXPECT_EQ(check, false); + + // case 1: 传入nullptr参数 + result = pagComposition->removeLayer(nullptr); + EXPECT_EQ(result == nullptr, true); + + // case 2: pagLayer不属于当前PAGComposition + auto emptyPAGLayer = PAGImageLayer::Make(100, 100, 100); + result = pagComposition->removeLayer(emptyPAGLayer); + EXPECT_EQ(result == nullptr, true); + + // case 3: PAGLayer是当前PAGComposition + result = pagComposition->removeLayer(pagComposition); + EXPECT_EQ(result == nullptr, true); } /** * 用例描述: ContainerTest removeLayerAt */ PAG_TEST_F(ContainerTest, removeLayerAt) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: index <0 - auto result = pagComposition->removeLayerAt(-1); - EXPECT_EQ(result, nullptr); - - // case 1: index 超出范围 - result = pagComposition->removeLayerAt(pagComposition->numChildren()); - EXPECT_EQ(result, nullptr); - - // case 2: 正常情况 - auto pagLayer = pagComposition->getLayerAt(0); - EXPECT_EQ(pagLayer->parent() == pagComposition, true); - result = pagComposition->removeLayerAt(0); - EXPECT_EQ(pagLayer->parent(), nullptr); - auto check = pagComposition->contains(pagLayer); - EXPECT_EQ(check, false); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: index <0 + auto result = pagComposition->removeLayerAt(-1); + EXPECT_EQ(result, nullptr); + + // case 1: index 超出范围 + result = pagComposition->removeLayerAt(pagComposition->numChildren()); + EXPECT_EQ(result, nullptr); + + // case 2: 正常情况 + auto pagLayer = pagComposition->getLayerAt(0); + EXPECT_EQ(pagLayer->parent() == pagComposition, true); + result = pagComposition->removeLayerAt(0); + EXPECT_EQ(pagLayer->parent(), nullptr); + auto check = pagComposition->contains(pagLayer); + EXPECT_EQ(check, false); } /** * 用例描述: ContainerTest removeAllLayers */ PAG_TEST_F(ContainerTest, removeAllLayers) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - auto layerCount = pagComposition->numChildren(); - EXPECT_LE(layerCount, 6); - auto pagLayer = pagComposition->getLayerAt(0); - EXPECT_TRUE(pagLayer->parent() == pagComposition); - pagComposition->removeAllLayers(); - layerCount = pagComposition->numChildren(); - EXPECT_EQ(layerCount, 0); - EXPECT_EQ(pagLayer->parent(), nullptr); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + auto layerCount = pagComposition->numChildren(); + EXPECT_LE(layerCount, 6); + auto pagLayer = pagComposition->getLayerAt(0); + EXPECT_TRUE(pagLayer->parent() == pagComposition); + pagComposition->removeAllLayers(); + layerCount = pagComposition->numChildren(); + EXPECT_EQ(layerCount, 0); + EXPECT_EQ(pagLayer->parent(), nullptr); } /** * 用例描述: ContainerTest swapLayerAt */ PAG_TEST_F(ContainerTest, swapLayerAt) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 - auto pagLayer0 = pagComposition->getLayerAt(0); - auto pagLayer1 = pagComposition->getLayerAt(1); - pagComposition->swapLayerAt(0, 1); - auto pagLayer00 = pagComposition->getLayerAt(0); - auto pagLayer01 = pagComposition->getLayerAt(1); - EXPECT_TRUE(pagLayer0 == pagLayer01); - EXPECT_TRUE(pagLayer1 == pagLayer00); - - // case 1: index1 范围内,index2 范围外 - auto pagLayer = pagComposition->getLayerAt(0); - pagComposition->swapLayerAt(0, -1); - auto index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - pagComposition->swapLayerAt(0, pagComposition->numChildren()); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - // case 2: index1 范围外,index2 范围内 - pagLayer = pagComposition->getLayerAt(0); - pagComposition->swapLayerAt(-1, 0); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - pagComposition->swapLayerAt(pagComposition->numChildren(), 0); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 + auto pagLayer0 = pagComposition->getLayerAt(0); + auto pagLayer1 = pagComposition->getLayerAt(1); + pagComposition->swapLayerAt(0, 1); + auto pagLayer00 = pagComposition->getLayerAt(0); + auto pagLayer01 = pagComposition->getLayerAt(1); + EXPECT_TRUE(pagLayer0 == pagLayer01); + EXPECT_TRUE(pagLayer1 == pagLayer00); + + // case 1: index1 范围内,index2 范围外 + auto pagLayer = pagComposition->getLayerAt(0); + pagComposition->swapLayerAt(0, -1); + auto index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + pagComposition->swapLayerAt(0, pagComposition->numChildren()); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + // case 2: index1 范围外,index2 范围内 + pagLayer = pagComposition->getLayerAt(0); + pagComposition->swapLayerAt(-1, 0); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + pagComposition->swapLayerAt(pagComposition->numChildren(), 0); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); } /** * 用例描述: ContainerTest swapLayer */ PAG_TEST_F(ContainerTest, swapLayer) { - auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); - // case 0: 正常情况 - auto pagLayer0 = pagComposition->getLayerAt(0); - auto pagLayer1 = pagComposition->getLayerAt(1); - pagComposition->swapLayer(pagLayer0, pagLayer1); - auto index0 = pagComposition->getLayerIndex(pagLayer0); - EXPECT_EQ(index0, 1); - auto index1 = pagComposition->getLayerIndex(pagLayer1); - EXPECT_EQ(index1, 0); - - // case 2: pagLayer1是nullptr 或者 pagLayer2是nullptr,另外一个是当前PAGComposition的子Layer - auto pagLayer = pagComposition->getLayerAt(0); - pagComposition->swapLayer(nullptr, pagLayer); - auto index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - pagLayer = pagComposition->getLayerAt(0); - pagComposition->swapLayer(pagLayer, nullptr); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - // case 3: pagLayer1指向另外一个PAGComposition的子Layer , pagLayer2是当前PAGComposition的子Layer - pagLayer = pagComposition->getLayerAt(0); - auto emptyLayer = PAGImageLayer::Make(100, 100, 100); - pagComposition->swapLayer(pagLayer, emptyLayer); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); - - pagLayer = pagComposition->getLayerAt(0); - pagComposition->swapLayer(emptyLayer, pagLayer); - index = pagComposition->getLayerIndex(pagLayer); - EXPECT_EQ(index, 0); + auto pagComposition = std::static_pointer_cast(TestPAGFile->getLayerAt(0)); + // case 0: 正常情况 + auto pagLayer0 = pagComposition->getLayerAt(0); + auto pagLayer1 = pagComposition->getLayerAt(1); + pagComposition->swapLayer(pagLayer0, pagLayer1); + auto index0 = pagComposition->getLayerIndex(pagLayer0); + EXPECT_EQ(index0, 1); + auto index1 = pagComposition->getLayerIndex(pagLayer1); + EXPECT_EQ(index1, 0); + + // case 2: pagLayer1是nullptr 或者 pagLayer2是nullptr,另外一个是当前PAGComposition的子Layer + auto pagLayer = pagComposition->getLayerAt(0); + pagComposition->swapLayer(nullptr, pagLayer); + auto index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + pagLayer = pagComposition->getLayerAt(0); + pagComposition->swapLayer(pagLayer, nullptr); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + // case 3: pagLayer1指向另外一个PAGComposition的子Layer , pagLayer2是当前PAGComposition的子Layer + pagLayer = pagComposition->getLayerAt(0); + auto emptyLayer = PAGImageLayer::Make(100, 100, 100); + pagComposition->swapLayer(pagLayer, emptyLayer); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); + + pagLayer = pagComposition->getLayerAt(0); + pagComposition->swapLayer(emptyLayer, pagLayer); + index = pagComposition->getLayerIndex(pagLayer); + EXPECT_EQ(index, 0); } /** * 用例描述: ContainerTest HitTestPoint */ PAG_TEST_F(ContainerTest, HitTestPoint) { - HitTestCase::HitTestPoint(TestPAGPlayer, TestPAGFile); + HitTestCase::HitTestPoint(TestPAGPlayer, TestPAGFile); } PAG_TEST_SUIT_WITH_PATH(VideoSequenceHitTestPoint, "../resources/apitest/video_sequence_test.pag") @@ -449,7 +452,7 @@ PAG_TEST_SUIT_WITH_PATH(VideoSequenceHitTestPoint, "../resources/apitest/video_s * 用例描述: 视频序列帧HitTest */ PAG_TEST_F(VideoSequenceHitTestPoint, VideoSequenceHitTestPoint) { - HitTestCase::VideoSequenceHitTestPoint(TestPAGPlayer, TestPAGFile); + HitTestCase::VideoSequenceHitTestPoint(TestPAGPlayer, TestPAGFile); } PAG_TEST_SUIT_WITH_PATH(BitmapSequenceHitTestPoint, "../resources/apitest/bitmap_sequence_test.pag") @@ -458,34 +461,34 @@ PAG_TEST_SUIT_WITH_PATH(BitmapSequenceHitTestPoint, "../resources/apitest/bitmap * 用例描述: 图片序列帧HitTest */ PAG_TEST_F(BitmapSequenceHitTestPoint, BitmapSequenceHitTestPoint) { - HitTestCase::BitmapSequenceHitTestPoint(TestPAGPlayer, TestPAGFile); + HitTestCase::BitmapSequenceHitTestPoint(TestPAGPlayer, TestPAGFile); } /** * 用例描述: GetLayersUnderPoint 边缘Case测试 */ PAG_TEST_F(ContainerTest, GetLayersUnderPointEdgeCase) { - HitTestCase::GetLayersUnderPointEdgeCase(TestPAGPlayer, TestPAGFile); + HitTestCase::GetLayersUnderPointEdgeCase(TestPAGPlayer, TestPAGFile); } /** * 用例描述: TrackMatte图层 GetLayersUnderPoint 测试 */ PAG_TEST_F(ContainerTest, GetLayersUnderPointTrackMatte) { - HitTestCase::GetLayersUnderPointTrackMatte(TestPAGPlayer, TestPAGFile); + HitTestCase::GetLayersUnderPointTrackMatte(TestPAGPlayer, TestPAGFile); } /** * 用例描述: Text图层 GetLayersUnderPoint 测试 */ PAG_TEST_F(ContainerTest, GetLayersUnderPointText) { - HitTestCase::GetLayersUnderPointText(TestPAGPlayer, TestPAGFile); + HitTestCase::GetLayersUnderPointText(TestPAGPlayer, TestPAGFile); } /** * 用例描述: Image图层 GetLayersUnderPoint 测试 */ PAG_TEST_F(ContainerTest, GetLayersUnderPointImage) { - HitTestCase::GetLayersUnderPointImage(TestPAGPlayer, TestPAGFile); + HitTestCase::GetLayersUnderPointImage(TestPAGPlayer, TestPAGFile); } } // namespace pag diff --git a/test/PAGFileTest.cpp b/test/PAGFileTest.cpp index 545ef9cb80..b56c7a89d0 100644 --- a/test/PAGFileTest.cpp +++ b/test/PAGFileTest.cpp @@ -36,96 +36,96 @@ PAG_TEST_SUIT_WITH_PATH(PAGFileBaseTest, PAG_CORRECT_FILE_PATH) * 用例描述: PAGFile基础信息获取 */ PAG_TEST_F(PAGFileBaseTest, TestPAGFileBase) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - //基本信息校验 - ASSERT_EQ(TestFile->duration(), 250); - ASSERT_EQ(TestFile->frameRate(), 25); - Color bgColor = {171, 161, 161}; - ASSERT_TRUE(TestFile->backgroundColor() == bgColor); - ASSERT_EQ(TestFile->width(), 720); - ASSERT_EQ(TestFile->height(), 1080); - ASSERT_EQ(TestFile->tagLevel(), 53); - ASSERT_EQ(TestFile->numLayers(), 6); - ASSERT_EQ(TestFile->numTexts(), 2); - ASSERT_EQ(TestFile->numImages(), 2); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + //基本信息校验 + ASSERT_EQ(TestFile->duration(), 250); + ASSERT_EQ(TestFile->frameRate(), 25); + Color bgColor = {171, 161, 161}; + ASSERT_TRUE(TestFile->backgroundColor() == bgColor); + ASSERT_EQ(TestFile->width(), 720); + ASSERT_EQ(TestFile->height(), 1080); + ASSERT_EQ(TestFile->tagLevel(), 53); + ASSERT_EQ(TestFile->numLayers(), 6); + ASSERT_EQ(TestFile->numTexts(), 2); + ASSERT_EQ(TestFile->numImages(), 2); } /** * 用例描述: PAGFile getImageAt接口校验 */ PAG_TEST_F(PAGFileBaseTest, TestPAGFileImage) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - // imageLayer 正常获取 - auto imageLayer = TestFile->getImageAt(1); - ASSERT_TRUE(imageLayer.size() > 0); - ASSERT_EQ(imageLayer[0]->name, "PAGImageLayer1"); - ASSERT_EQ(TestFile->getEditableIndex(imageLayer[0]), 1); - // imageLayer 异常获取 <0 - imageLayer = TestFile->getImageAt(-1); - ASSERT_TRUE(imageLayer.size() == 0); - // imageLayer 异常获取 >= size - imageLayer = TestFile->getImageAt(TestFile->numImages()); - ASSERT_TRUE(imageLayer.size() == 0); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + // imageLayer 正常获取 + auto imageLayer = TestFile->getImageAt(1); + ASSERT_TRUE(imageLayer.size() > 0); + ASSERT_EQ(imageLayer[0]->name, "PAGImageLayer1"); + ASSERT_EQ(TestFile->getEditableIndex(imageLayer[0]), 1); + // imageLayer 异常获取 <0 + imageLayer = TestFile->getImageAt(-1); + ASSERT_TRUE(imageLayer.size() == 0); + // imageLayer 异常获取 >= size + imageLayer = TestFile->getImageAt(TestFile->numImages()); + ASSERT_TRUE(imageLayer.size() == 0); } /** * 用例描述: PAGFile getTextAt校验 */ PAG_TEST_F(PAGFileBaseTest, TestPAGFileText) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - // textLayer 正常获取 >= size - // ASSERT_EQ(TestFile->getEditableIndex(textLayer), 1); - // textLayer 异常获取 >= size - auto textLayer = TestFile->getTextAt(TestFile->numTexts()); - ASSERT_EQ(textLayer, nullptr); - // textLayer 异常获取 < 0 - textLayer = TestFile->getTextAt(-1); - ASSERT_EQ(textLayer, nullptr); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + // textLayer 正常获取 >= size + // ASSERT_EQ(TestFile->getEditableIndex(textLayer), 1); + // textLayer 异常获取 >= size + auto textLayer = TestFile->getTextAt(TestFile->numTexts()); + ASSERT_EQ(textLayer, nullptr); + // textLayer 异常获取 < 0 + textLayer = TestFile->getTextAt(-1); + ASSERT_EQ(textLayer, nullptr); } /** * 用例描述: PAGFile getTextData校验 */ PAG_TEST_F(PAGFileBaseTest, TestPAGFileTextData) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - // textData 异常获取 >= size - auto textData = TestFile->getTextData(TestFile->numTexts()); - ASSERT_EQ(textData, nullptr); - // textData 异常获取 < 0 - textData = TestFile->getTextData(-1); - ASSERT_EQ(textData, nullptr); - // auto fontFamily = textData->fontFamily; + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + // textData 异常获取 >= size + auto textData = TestFile->getTextData(TestFile->numTexts()); + ASSERT_EQ(textData, nullptr); + // textData 异常获取 < 0 + textData = TestFile->getTextData(-1); + ASSERT_EQ(textData, nullptr); + // auto fontFamily = textData->fontFamily; } /** * 用例描述: PAGFile编解码校验 */ PAG_TEST_F(PAGFileBaseTest, TestPAGFileEncodeDecode) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - // encode decode验证 - //验证文件数据与测试结果是否一致 - auto encodeByteData = Codec::Encode(TestFile); // 再编码检查一下 - auto verifyByteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); - ASSERT_EQ(verifyByteData->length(), encodeByteData->length()); - auto verifyData = verifyByteData->data(); - auto encodeData = encodeByteData->data(); - for (size_t i = 0; i < encodeByteData->length(); ++i) { - ASSERT_EQ(verifyData[i], encodeData[i]); - } + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + // encode decode验证 + //验证文件数据与测试结果是否一致 + auto encodeByteData = Codec::Encode(TestFile); // 再编码检查一下 + auto verifyByteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); + ASSERT_EQ(verifyByteData->length(), encodeByteData->length()); + auto verifyData = verifyByteData->data(); + auto encodeData = encodeByteData->data(); + for (size_t i = 0; i < encodeByteData->length(); ++i) { + ASSERT_EQ(verifyData[i], encodeData[i]); + } } PAG_TEST_SUIT_WITH_PATH(PAGFileComplexTest, PAG_COMPLEX_FILE_PATH) @@ -134,222 +134,222 @@ PAG_TEST_SUIT_WITH_PATH(PAGFileComplexTest, PAG_COMPLEX_FILE_PATH) * 用例描述: PAGFile numImages 接口 */ PAG_TEST_F(PAGFileComplexTest, numImages) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - ASSERT_EQ(TestFile->numImages(), 1); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + ASSERT_EQ(TestFile->numImages(), 1); } /** * 用例描述: PAGFile numTexts 接口 */ PAG_TEST_F(PAGFileComplexTest, numTexts) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - ASSERT_EQ(TestFile->numTexts(), 4); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + ASSERT_EQ(TestFile->numTexts(), 4); } /** * 用例描述: PAGFile numLayers 接口 */ PAG_TEST_F(PAGFileComplexTest, numLayers) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - ASSERT_EQ(TestFile->numLayers(), 10); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + ASSERT_EQ(TestFile->numLayers(), 10); } /** * 用例描述: PAGFile tagLevel 接口 */ PAG_TEST_F(PAGFileComplexTest, tagLevel) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - ASSERT_EQ(TestFile->tagLevel(), 53); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + ASSERT_EQ(TestFile->tagLevel(), 53); } /** * 用例描述: PAGFile rootLayer 接口 */ PAG_TEST_F(PAGFileComplexTest, rootLayer) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - // rootLayer 校验 - auto fileRootLayer = TestFile->getRootLayer(); - ASSERT_EQ(fileRootLayer->composition->type(), CompositionType::Vector); - ASSERT_EQ(fileRootLayer->name, ""); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + // rootLayer 校验 + auto fileRootLayer = TestFile->getRootLayer(); + ASSERT_EQ(fileRootLayer->composition->type(), CompositionType::Vector); + ASSERT_EQ(fileRootLayer->name, ""); } /** * 用例描述: PAGFile getImageAt 接口 */ PAG_TEST_F(PAGFileComplexTest, getImageAt) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - // imageLayer 正常获取 - auto imageLayer = TestFile->getImageAt(0); - ASSERT_TRUE(imageLayer.size() > 0); - ASSERT_EQ(imageLayer[0]->name, "PAGImageLayer2"); - ASSERT_EQ(TestFile->getEditableIndex(imageLayer[0]), 0); - // imageLayer 异常获取 <0 - imageLayer = TestFile->getImageAt(-1); - ASSERT_TRUE(imageLayer.size() == 0); - // imageLayer 异常获取 >= size - imageLayer = TestFile->getImageAt(TestFile->numImages()); - ASSERT_TRUE(imageLayer.size() == 0); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + // imageLayer 正常获取 + auto imageLayer = TestFile->getImageAt(0); + ASSERT_TRUE(imageLayer.size() > 0); + ASSERT_EQ(imageLayer[0]->name, "PAGImageLayer2"); + ASSERT_EQ(TestFile->getEditableIndex(imageLayer[0]), 0); + // imageLayer 异常获取 <0 + imageLayer = TestFile->getImageAt(-1); + ASSERT_TRUE(imageLayer.size() == 0); + // imageLayer 异常获取 >= size + imageLayer = TestFile->getImageAt(TestFile->numImages()); + ASSERT_TRUE(imageLayer.size() == 0); } /** * 用例描述: PAGFile getTextAt 接口 */ PAG_TEST_F(PAGFileComplexTest, getTextAt) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - // textLayer 正常获取 - auto textLayer = TestFile->getTextAt(0); - ASSERT_EQ(TestFile->getEditableIndex(textLayer), 0); - ASSERT_EQ(textLayer->name, "ReplaceTextLayer"); - auto textData1 = TestFile->getTextData(0); - auto textData2 = textLayer->getTextDocument(); - ASSERT_EQ(textData1->fontFamily, textData2->fontFamily); - ASSERT_EQ(textData1->fontStyle, textData2->fontStyle); - ASSERT_EQ(textData1->fontSize, textData2->fontSize); - // textLayer 异常获取 >= size - textLayer = TestFile->getTextAt(TestFile->numTexts()); - ASSERT_EQ(textLayer, nullptr); - // textLayer 异常获取 < 0 - textLayer = TestFile->getTextAt(-1); - ASSERT_EQ(textLayer, nullptr); + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + // textLayer 正常获取 + auto textLayer = TestFile->getTextAt(0); + ASSERT_EQ(TestFile->getEditableIndex(textLayer), 0); + ASSERT_EQ(textLayer->name, "ReplaceTextLayer"); + auto textData1 = TestFile->getTextData(0); + auto textData2 = textLayer->getTextDocument(); + ASSERT_EQ(textData1->fontFamily, textData2->fontFamily); + ASSERT_EQ(textData1->fontStyle, textData2->fontStyle); + ASSERT_EQ(textData1->fontSize, textData2->fontSize); + // textLayer 异常获取 >= size + textLayer = TestFile->getTextAt(TestFile->numTexts()); + ASSERT_EQ(textLayer, nullptr); + // textLayer 异常获取 < 0 + textLayer = TestFile->getTextAt(-1); + ASSERT_EQ(textLayer, nullptr); } /** * 用例描述: PAGFile textData 接口 */ PAG_TEST_F(PAGFileComplexTest, getTextData) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - // textData 异常获取 >= size - auto textData = TestFile->getTextData(TestFile->numTexts()); - ASSERT_EQ(textData, nullptr); - // textData 异常获取 < 0 - textData = TestFile->getTextData(-1); - ASSERT_EQ(textData, nullptr); - // auto fontFamily = textData->fontFamily; + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + // textData 异常获取 >= size + auto textData = TestFile->getTextData(TestFile->numTexts()); + ASSERT_EQ(textData, nullptr); + // textData 异常获取 < 0 + textData = TestFile->getTextData(-1); + ASSERT_EQ(textData, nullptr); + // auto fontFamily = textData->fontFamily; } /** * 用例描述: PAGFile基础功能 */ PAG_TEST_F(PAGFileComplexTest, TestPAGFile) { - ASSERT_NE(TestPAGFile, nullptr); - auto TestFile = TestPAGFile->getFile(); - ASSERT_NE(TestFile, nullptr); - - //基本信息校验 - ASSERT_EQ(TestFile->duration(), 250); - ASSERT_EQ(TestFile->frameRate(), 25); - Color bgColor = {171, 161, 161}; - ASSERT_TRUE(TestFile->backgroundColor() == bgColor); - ASSERT_EQ(TestFile->width(), 720); - ASSERT_EQ(TestFile->height(), 1080); - - auto composition = static_cast(TestFile->getRootLayer()->composition); - ASSERT_EQ(static_cast(composition->layers.size()), 5); - ASSERT_EQ(composition->layers[0]->type(), LayerType::Text); - ASSERT_EQ(composition->layers[0]->name, "ReplaceTextLayer"); - ASSERT_EQ(composition->layers[1]->type(), LayerType::PreCompose); - ASSERT_EQ(composition->layers[1]->name, "video_alpha_bmp"); - auto sublayerComposition = static_cast(composition->layers[1])->composition; - ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); - ASSERT_EQ(composition->layers[2]->type(), LayerType::PreCompose); - ASSERT_EQ(composition->layers[2]->name, "PAGImageLayer2_bmp"); - sublayerComposition = static_cast(composition->layers[2])->composition; - ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); - ASSERT_EQ(composition->layers[3]->type(), LayerType::PreCompose); - ASSERT_EQ(composition->layers[3]->name, "PAGImageLayer3_bmp"); - sublayerComposition = static_cast(composition->layers[3])->composition; - ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); - ASSERT_EQ(composition->layers[4]->type(), LayerType::PreCompose); - ASSERT_EQ(composition->layers[4]->name, "RootLayer"); - sublayerComposition = static_cast(composition->layers[4])->composition; - ASSERT_EQ(sublayerComposition->type(), CompositionType::Vector); - - // encode decode验证 - //验证文件数据与测试结果是否一致 - auto encodeByteData = Codec::Encode(TestFile); // 再编码检查一下 - auto verifyByteData = ByteData::FromPath(PAG_COMPLEX_FILE_PATH); - ASSERT_EQ(verifyByteData->length(), encodeByteData->length()); - auto verifyData = verifyByteData->data(); - auto encodeData = encodeByteData->data(); - for (size_t i = 0; i < encodeByteData->length(); ++i) { - ASSERT_EQ(verifyData[i], encodeData[i]); - } + ASSERT_NE(TestPAGFile, nullptr); + auto TestFile = TestPAGFile->getFile(); + ASSERT_NE(TestFile, nullptr); + + //基本信息校验 + ASSERT_EQ(TestFile->duration(), 250); + ASSERT_EQ(TestFile->frameRate(), 25); + Color bgColor = {171, 161, 161}; + ASSERT_TRUE(TestFile->backgroundColor() == bgColor); + ASSERT_EQ(TestFile->width(), 720); + ASSERT_EQ(TestFile->height(), 1080); + + auto composition = static_cast(TestFile->getRootLayer()->composition); + ASSERT_EQ(static_cast(composition->layers.size()), 5); + ASSERT_EQ(composition->layers[0]->type(), LayerType::Text); + ASSERT_EQ(composition->layers[0]->name, "ReplaceTextLayer"); + ASSERT_EQ(composition->layers[1]->type(), LayerType::PreCompose); + ASSERT_EQ(composition->layers[1]->name, "video_alpha_bmp"); + auto sublayerComposition = static_cast(composition->layers[1])->composition; + ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); + ASSERT_EQ(composition->layers[2]->type(), LayerType::PreCompose); + ASSERT_EQ(composition->layers[2]->name, "PAGImageLayer2_bmp"); + sublayerComposition = static_cast(composition->layers[2])->composition; + ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); + ASSERT_EQ(composition->layers[3]->type(), LayerType::PreCompose); + ASSERT_EQ(composition->layers[3]->name, "PAGImageLayer3_bmp"); + sublayerComposition = static_cast(composition->layers[3])->composition; + ASSERT_EQ(sublayerComposition->type(), CompositionType::Video); + ASSERT_EQ(composition->layers[4]->type(), LayerType::PreCompose); + ASSERT_EQ(composition->layers[4]->name, "RootLayer"); + sublayerComposition = static_cast(composition->layers[4])->composition; + ASSERT_EQ(sublayerComposition->type(), CompositionType::Vector); + + // encode decode验证 + //验证文件数据与测试结果是否一致 + auto encodeByteData = Codec::Encode(TestFile); // 再编码检查一下 + auto verifyByteData = ByteData::FromPath(PAG_COMPLEX_FILE_PATH); + ASSERT_EQ(verifyByteData->length(), encodeByteData->length()); + auto verifyData = verifyByteData->data(); + auto encodeData = encodeByteData->data(); + for (size_t i = 0; i < encodeByteData->length(); ++i) { + ASSERT_EQ(verifyData[i], encodeData[i]); + } } /** * 用例描述: ByteData解码测试 */ PAG_TEST(PAGFileLoadTest, byteData) { - std::shared_ptr file; - // load from byte - auto byteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); - ASSERT_TRUE(byteData != nullptr); - ASSERT_TRUE(byteData->data() != nullptr); - ASSERT_TRUE(byteData->length() != 0); + std::shared_ptr file; + // load from byte + auto byteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); + ASSERT_TRUE(byteData != nullptr); + ASSERT_TRUE(byteData->data() != nullptr); + ASSERT_TRUE(byteData->length() != 0); } /** * 用例描述: PAGFile解码测试 */ PAG_TEST(PAGFileLoadTest, loadTest) { - std::shared_ptr file; - - // load from byte - auto byteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); - ASSERT_TRUE(byteData != nullptr); - file = PAGFile::Load(byteData->data(), byteData->length()); - ASSERT_TRUE(file != nullptr); - - // error length - file = PAGFile::Load(byteData->data(), byteData->length() - 20); - ASSERT_TRUE(file == nullptr); - - // larger length, correct data - file = PAGFile::Load(byteData->data(), byteData->length() + 20); - ASSERT_TRUE(file != nullptr); - - // error data - const void* errorBytes = "test error data can be loaded. "; - file = PAGFile::Load(errorBytes, 31); - ASSERT_TRUE(file == nullptr); - - // empty data - errorBytes = ""; - file = PAGFile::Load(errorBytes, 0); - ASSERT_TRUE(file == nullptr); - - // load from path - file = PAGFile::Load(PAG_CORRECT_FILE_PATH); - ASSERT_TRUE(file != nullptr); - - // error path - file = PAGFile::Load(PAG_ERROR_FILE_PATH_ERRPATH); - ASSERT_TRUE(file == nullptr); - - // error file content - file = PAGFile::Load(PAG_ERROR_FILE_PATH_ERRFILE); - ASSERT_TRUE(file == nullptr); - - // empty path - file = PAGFile::Load(PAG_ERROR_FILE_PATH_EMPTYPATH); - ASSERT_TRUE(file == nullptr); + std::shared_ptr file; + + // load from byte + auto byteData = ByteData::FromPath(PAG_CORRECT_FILE_PATH); + ASSERT_TRUE(byteData != nullptr); + file = PAGFile::Load(byteData->data(), byteData->length()); + ASSERT_TRUE(file != nullptr); + + // error length + file = PAGFile::Load(byteData->data(), byteData->length() - 20); + ASSERT_TRUE(file == nullptr); + + // larger length, correct data + file = PAGFile::Load(byteData->data(), byteData->length() + 20); + ASSERT_TRUE(file != nullptr); + + // error data + const void* errorBytes = "test error data can be loaded. "; + file = PAGFile::Load(errorBytes, 31); + ASSERT_TRUE(file == nullptr); + + // empty data + errorBytes = ""; + file = PAGFile::Load(errorBytes, 0); + ASSERT_TRUE(file == nullptr); + + // load from path + file = PAGFile::Load(PAG_CORRECT_FILE_PATH); + ASSERT_TRUE(file != nullptr); + + // error path + file = PAGFile::Load(PAG_ERROR_FILE_PATH_ERRPATH); + ASSERT_TRUE(file == nullptr); + + // error file content + file = PAGFile::Load(PAG_ERROR_FILE_PATH_ERRFILE); + ASSERT_TRUE(file == nullptr); + + // empty path + file = PAGFile::Load(PAG_ERROR_FILE_PATH_EMPTYPATH); + ASSERT_TRUE(file == nullptr); } PAG_TEST_CASE(PAGFileContainerTest) @@ -358,149 +358,149 @@ PAG_TEST_CASE(PAGFileContainerTest) * 用例描述: PAGFile children编辑测试 */ PAG_TEST_F(PAGFileContainerTest, getLayersByEditableIndex) { - TestPAGFile->removeAllLayers(); - ASSERT_EQ(TestPAGFile->numChildren(), 0); - auto rootLayer = PAGFile::Load(DEFAULT_PAG_PATH); - auto pagCom = std::static_pointer_cast(rootLayer->getLayerAt(0)); - int size = pagCom->numChildren(); - for (int i = 0; i < size; i++) { - auto layer = pagCom->getLayerAt(0); - layer->setCurrentTime(3 * 1000000); - TestPAGFile->addLayer(pagCom->getLayerAt(0)); - } - - ASSERT_EQ(TestPAGFile->width(), 720); - ASSERT_EQ(TestPAGFile->height(), 1080); - ASSERT_EQ(TestPAGFile->numChildren(), 6); - ASSERT_EQ(TestPAGFile->numImages(), 2); - - auto editableLayers = TestPAGFile->getLayersByEditableIndex(0, LayerType::Text); - ASSERT_EQ(static_cast(editableLayers.size()), 1); - ASSERT_EQ(editableLayers[0]->layerName(), "PAGTextLayer2"); - editableLayers = TestPAGFile->getLayersByEditableIndex(1, LayerType::Text); - ASSERT_EQ(static_cast(editableLayers.size()), 1); - ASSERT_EQ(editableLayers[0]->layerName(), "PAGTextLayer1"); - editableLayers = TestPAGFile->getLayersByEditableIndex(2, LayerType::Text); - ASSERT_EQ(static_cast(editableLayers.size()), 0); - editableLayers = TestPAGFile->getLayersByEditableIndex(0, LayerType::Image); - ASSERT_EQ(static_cast(editableLayers.size()), 1); - ASSERT_EQ(editableLayers[0]->layerName(), "PAGImageLayer2"); - editableLayers = TestPAGFile->getLayersByEditableIndex(1, LayerType::Image); - ASSERT_EQ(static_cast(editableLayers.size()), 1); - ASSERT_EQ(editableLayers[0]->layerName(), "PAGImageLayer1"); - editableLayers = TestPAGFile->getLayersByEditableIndex(2, LayerType::Image); - ASSERT_EQ(static_cast(editableLayers.size()), 0); - - auto imageLayer1 = std::static_pointer_cast(TestPAGFile->getLayerAt(2)); - ASSERT_NE(imageLayer1, nullptr); - ASSERT_EQ(imageLayer1->layerName(), "PAGImageLayer1"); - ASSERT_EQ(TestPAGFile->getLayerIndex(imageLayer1), 2); - ASSERT_TRUE(TestPAGFile->contains(imageLayer1)); - - auto imageLayer2 = std::static_pointer_cast(TestPAGFile->getLayerAt(3)); - ASSERT_NE(imageLayer2, nullptr); - ASSERT_EQ(imageLayer2->layerName(), "PAGImageLayer2"); - - TestPAGFile->swapLayer(imageLayer1, imageLayer2); - TestPAGPlayer->flush(); - auto swapLayerMd5 = getMd5FromSnap(); - - TestPAGFile->swapLayerAt(2, 3); - TestPAGPlayer->flush(); - auto swapLayerAtMd5 = getMd5FromSnap(); - - TestPAGFile->setLayerIndex(imageLayer1, 3); - TestPAGPlayer->flush(); - auto setLayerIndexMd5 = getMd5FromSnap(); - - TestPAGFile->removeLayer(imageLayer1); - TestPAGPlayer->flush(); - auto removeLayerMd5 = getMd5FromSnap(); - - TestPAGFile->removeLayerAt(2); - TestPAGPlayer->flush(); - auto removeLayerAtMd5 = getMd5FromSnap(); - - TestPAGFile->removeAllLayers(); - TestPAGPlayer->flush(); - ASSERT_EQ(TestPAGFile->numChildren(), 0); - auto removeAllLayersMd5 = getMd5FromSnap(); - - auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); - auto root2 = pagFile2; - auto pagComposition2 = std::static_pointer_cast(root2->getLayerAt(0)); - auto imageLayer = pagComposition2->getLayerAt(2); - TestPAGFile->addLayer(imageLayer); - TestPAGPlayer->flush(); - auto addLayerMd5 = getMd5FromSnap(); - - TestPAGFile->addLayerAt(pagComposition2->getLayerAt(3), 0); - TestPAGPlayer->flush(); - auto addLayerAtMd5 = getMd5FromSnap(); - - TestPAGFile->contains(nullptr); - TestPAGFile->removeLayer(nullptr); - TestPAGFile->removeLayerAt(-2); - - TestPAGFile->addLayer(nullptr); - TestPAGFile->addLayerAt(imageLayer2, 30); - - TestPAGFile->addLayerAt(nullptr, 0); - TestPAGFile->swapLayer(nullptr, imageLayer2); - - auto image = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); - TestPAGFile->replaceImage(0, image); - TestPAGPlayer->flush(); - auto replaceImageMd5 = getMd5FromSnap(); - - auto textData = std::shared_ptr(new TextDocument()); - textData->text = "测试ceshi"; - textData->fillColor = Red; - TestPAGFile->replaceText(0, textData); - TestPAGPlayer->flush(); - auto replaceTextMd5 = getMd5FromSnap(); - - json out = { - {"swapLayerMd5", swapLayerMd5}, - {"setLayerIndexMd5", setLayerIndexMd5}, - {"removeLayerMd5", removeLayerMd5}, - {"removeLayerAtMd5", removeLayerAtMd5}, - {"removeAllLayersMd5", removeAllLayersMd5}, - {"addLayerMd5", addLayerMd5}, - {"addLayerAt", addLayerAtMd5}, - {"replaceImageMd5", replaceImageMd5}, - {"replaceTextMd5", replaceTextMd5}, - }; - PAGTestEnvironment::DumpJson["PAGFileTest"]["PAGFileContainerTest"] = out; + TestPAGFile->removeAllLayers(); + ASSERT_EQ(TestPAGFile->numChildren(), 0); + auto rootLayer = PAGFile::Load(DEFAULT_PAG_PATH); + auto pagCom = std::static_pointer_cast(rootLayer->getLayerAt(0)); + int size = pagCom->numChildren(); + for (int i = 0; i < size; i++) { + auto layer = pagCom->getLayerAt(0); + layer->setCurrentTime(3 * 1000000); + TestPAGFile->addLayer(pagCom->getLayerAt(0)); + } + + ASSERT_EQ(TestPAGFile->width(), 720); + ASSERT_EQ(TestPAGFile->height(), 1080); + ASSERT_EQ(TestPAGFile->numChildren(), 6); + ASSERT_EQ(TestPAGFile->numImages(), 2); + + auto editableLayers = TestPAGFile->getLayersByEditableIndex(0, LayerType::Text); + ASSERT_EQ(static_cast(editableLayers.size()), 1); + ASSERT_EQ(editableLayers[0]->layerName(), "PAGTextLayer2"); + editableLayers = TestPAGFile->getLayersByEditableIndex(1, LayerType::Text); + ASSERT_EQ(static_cast(editableLayers.size()), 1); + ASSERT_EQ(editableLayers[0]->layerName(), "PAGTextLayer1"); + editableLayers = TestPAGFile->getLayersByEditableIndex(2, LayerType::Text); + ASSERT_EQ(static_cast(editableLayers.size()), 0); + editableLayers = TestPAGFile->getLayersByEditableIndex(0, LayerType::Image); + ASSERT_EQ(static_cast(editableLayers.size()), 1); + ASSERT_EQ(editableLayers[0]->layerName(), "PAGImageLayer2"); + editableLayers = TestPAGFile->getLayersByEditableIndex(1, LayerType::Image); + ASSERT_EQ(static_cast(editableLayers.size()), 1); + ASSERT_EQ(editableLayers[0]->layerName(), "PAGImageLayer1"); + editableLayers = TestPAGFile->getLayersByEditableIndex(2, LayerType::Image); + ASSERT_EQ(static_cast(editableLayers.size()), 0); + + auto imageLayer1 = std::static_pointer_cast(TestPAGFile->getLayerAt(2)); + ASSERT_NE(imageLayer1, nullptr); + ASSERT_EQ(imageLayer1->layerName(), "PAGImageLayer1"); + ASSERT_EQ(TestPAGFile->getLayerIndex(imageLayer1), 2); + ASSERT_TRUE(TestPAGFile->contains(imageLayer1)); + + auto imageLayer2 = std::static_pointer_cast(TestPAGFile->getLayerAt(3)); + ASSERT_NE(imageLayer2, nullptr); + ASSERT_EQ(imageLayer2->layerName(), "PAGImageLayer2"); + + TestPAGFile->swapLayer(imageLayer1, imageLayer2); + TestPAGPlayer->flush(); + auto swapLayerMd5 = getMd5FromSnap(); + + TestPAGFile->swapLayerAt(2, 3); + TestPAGPlayer->flush(); + auto swapLayerAtMd5 = getMd5FromSnap(); + + TestPAGFile->setLayerIndex(imageLayer1, 3); + TestPAGPlayer->flush(); + auto setLayerIndexMd5 = getMd5FromSnap(); + + TestPAGFile->removeLayer(imageLayer1); + TestPAGPlayer->flush(); + auto removeLayerMd5 = getMd5FromSnap(); + + TestPAGFile->removeLayerAt(2); + TestPAGPlayer->flush(); + auto removeLayerAtMd5 = getMd5FromSnap(); + + TestPAGFile->removeAllLayers(); + TestPAGPlayer->flush(); + ASSERT_EQ(TestPAGFile->numChildren(), 0); + auto removeAllLayersMd5 = getMd5FromSnap(); + + auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); + auto root2 = pagFile2; + auto pagComposition2 = std::static_pointer_cast(root2->getLayerAt(0)); + auto imageLayer = pagComposition2->getLayerAt(2); + TestPAGFile->addLayer(imageLayer); + TestPAGPlayer->flush(); + auto addLayerMd5 = getMd5FromSnap(); + + TestPAGFile->addLayerAt(pagComposition2->getLayerAt(3), 0); + TestPAGPlayer->flush(); + auto addLayerAtMd5 = getMd5FromSnap(); + + TestPAGFile->contains(nullptr); + TestPAGFile->removeLayer(nullptr); + TestPAGFile->removeLayerAt(-2); + + TestPAGFile->addLayer(nullptr); + TestPAGFile->addLayerAt(imageLayer2, 30); + + TestPAGFile->addLayerAt(nullptr, 0); + TestPAGFile->swapLayer(nullptr, imageLayer2); + + auto image = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); + TestPAGFile->replaceImage(0, image); + TestPAGPlayer->flush(); + auto replaceImageMd5 = getMd5FromSnap(); + + auto textData = std::shared_ptr(new TextDocument()); + textData->text = "测试ceshi"; + textData->fillColor = Red; + TestPAGFile->replaceText(0, textData); + TestPAGPlayer->flush(); + auto replaceTextMd5 = getMd5FromSnap(); + + json out = { + {"swapLayerMd5", swapLayerMd5}, + {"setLayerIndexMd5", setLayerIndexMd5}, + {"removeLayerMd5", removeLayerMd5}, + {"removeLayerAtMd5", removeLayerAtMd5}, + {"removeAllLayersMd5", removeAllLayersMd5}, + {"addLayerMd5", addLayerMd5}, + {"addLayerAt", addLayerAtMd5}, + {"replaceImageMd5", replaceImageMd5}, + {"replaceTextMd5", replaceTextMd5}, + }; + PAGTestEnvironment::DumpJson["PAGFileTest"]["PAGFileContainerTest"] = out; #ifdef COMPARE_JSON_PATH - auto cAddLayerAt = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["addLayerAt"]; - EXPECT_EQ(cAddLayerAt.get(), addLayerAtMd5); - auto cAddLayerMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["addLayerMd5"]; - EXPECT_EQ(cAddLayerMd5.get(), addLayerMd5); - auto cRemoveAllLayersMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeAllLayersMd5"]; - EXPECT_EQ(cRemoveAllLayersMd5.get(), removeAllLayersMd5); - auto cRemoveLayerAtMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeLayerAtMd5"]; - EXPECT_EQ(cRemoveLayerAtMd5.get(), removeLayerAtMd5); - auto cRemoveLayerMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeLayerMd5"]; - EXPECT_EQ(cRemoveLayerMd5.get(), removeLayerMd5); - auto cSetLayerIndexMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["setLayerIndexMd5"]; - EXPECT_EQ(cSetLayerIndexMd5.get(), setLayerIndexMd5); - auto cSwapLayerMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["swapLayerMd5"]; - EXPECT_EQ(cSwapLayerMd5.get(), swapLayerMd5); - auto cReplaceImageMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["replaceImageMd5"]; - EXPECT_EQ(cReplaceImageMd5.get(), replaceImageMd5); - auto cReplaceTextMd5 = - PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["replaceTextMd5"]; - EXPECT_EQ(cReplaceTextMd5.get(), replaceTextMd5); + auto cAddLayerAt = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["addLayerAt"]; + EXPECT_EQ(cAddLayerAt.get(), addLayerAtMd5); + auto cAddLayerMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["addLayerMd5"]; + EXPECT_EQ(cAddLayerMd5.get(), addLayerMd5); + auto cRemoveAllLayersMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeAllLayersMd5"]; + EXPECT_EQ(cRemoveAllLayersMd5.get(), removeAllLayersMd5); + auto cRemoveLayerAtMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeLayerAtMd5"]; + EXPECT_EQ(cRemoveLayerAtMd5.get(), removeLayerAtMd5); + auto cRemoveLayerMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["removeLayerMd5"]; + EXPECT_EQ(cRemoveLayerMd5.get(), removeLayerMd5); + auto cSetLayerIndexMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["setLayerIndexMd5"]; + EXPECT_EQ(cSetLayerIndexMd5.get(), setLayerIndexMd5); + auto cSwapLayerMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["swapLayerMd5"]; + EXPECT_EQ(cSwapLayerMd5.get(), swapLayerMd5); + auto cReplaceImageMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["replaceImageMd5"]; + EXPECT_EQ(cReplaceImageMd5.get(), replaceImageMd5); + auto cReplaceTextMd5 = + PAGTestEnvironment::CompareJson["PAGFileTest"]["PAGFileContainerTest"]["replaceTextMd5"]; + EXPECT_EQ(cReplaceTextMd5.get(), replaceTextMd5); #endif } @@ -510,21 +510,21 @@ PAG_TEST_CASE_WITH_PATH(PAGFileTimeStretchRepeat, "../resources/apitest/test_rep * 用例描述: PAGFile时间伸缩属性-Repeat测试 */ PAG_TEST_F(PAGFileTimeStretchRepeat, timeStretch) { - TestPAGFile->setDuration(TestPAGFile->duration() * 2); - //第1帧 - TestPAGFile->setCurrentTime(1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_1 = MakeSnapshot(TestPAGSurface); - std::string md5 = DumpMD5(skImage_1); - //第61帧 - TestPAGFile->setCurrentTime(2000000ll + 1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_61 = MakeSnapshot(TestPAGSurface); - std::string compMd5 = DumpMD5(skImage_61); - ASSERT_EQ(md5, compMd5); - TraceIf(skImage_1, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeate_1.png", md5 != compMd5); - TraceIf(skImage_61, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeate_61.png", - md5 != compMd5); + TestPAGFile->setDuration(TestPAGFile->duration() * 2); + //第1帧 + TestPAGFile->setCurrentTime(1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_1 = MakeSnapshot(TestPAGSurface); + std::string md5 = DumpMD5(skImage_1); + //第61帧 + TestPAGFile->setCurrentTime(2000000ll + 1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_61 = MakeSnapshot(TestPAGSurface); + std::string compMd5 = DumpMD5(skImage_61); + ASSERT_EQ(md5, compMd5); + TraceIf(skImage_1, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeate_1.png", md5 != compMd5); + TraceIf(skImage_61, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeate_61.png", + md5 != compMd5); } PAG_TEST_CASE_WITH_PATH(PAGFileTimeStretchRepeatInverted, @@ -534,22 +534,22 @@ PAG_TEST_CASE_WITH_PATH(PAGFileTimeStretchRepeatInverted, * 用例描述: PAGFile时间伸缩属性-RepeatInverted测试 */ PAG_TEST_F(PAGFileTimeStretchRepeatInverted, timeStretch) { - TestPAGFile->setDuration(TestPAGFile->duration() * 2); - //第1帧 - TestPAGFile->setCurrentTime(1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_1 = MakeSnapshot(TestPAGSurface); - std::string md5 = DumpMD5(skImage_1); - //第198帧 - TestPAGFile->setCurrentTime(2000000ll - 2 * 1000000ll / 30 + 2000000ll); - TestPAGPlayer->flush(); - auto skImage_198 = MakeSnapshot(TestPAGSurface); - std::string compMd5 = DumpMD5(skImage_198); - ASSERT_EQ(md5, compMd5); - TraceIf(skImage_1, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeateInverted_1.png", - md5 != compMd5); - TraceIf(skImage_198, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeateInverted_198.png", - md5 != compMd5); + TestPAGFile->setDuration(TestPAGFile->duration() * 2); + //第1帧 + TestPAGFile->setCurrentTime(1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_1 = MakeSnapshot(TestPAGSurface); + std::string md5 = DumpMD5(skImage_1); + //第198帧 + TestPAGFile->setCurrentTime(2000000ll - 2 * 1000000ll / 30 + 2000000ll); + TestPAGPlayer->flush(); + auto skImage_198 = MakeSnapshot(TestPAGSurface); + std::string compMd5 = DumpMD5(skImage_198); + ASSERT_EQ(md5, compMd5); + TraceIf(skImage_1, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeateInverted_1.png", + md5 != compMd5); + TraceIf(skImage_198, "../test/out/test_repeat.pag_PAGFileTimeStretchRepeateInverted_198.png", + md5 != compMd5); } PAG_TEST_CASE_WITH_PATH(PAGFileTimeStretchScale, "../resources/apitest/test_scale.pag") @@ -558,92 +558,92 @@ PAG_TEST_CASE_WITH_PATH(PAGFileTimeStretchScale, "../resources/apitest/test_scal * 用例描述: PAGFile时间伸缩属性-Scale测试 */ PAG_TEST_F(PAGFileTimeStretchScale, timeStretch) { - //第30帧 - TestPAGFile->setCurrentTime(30 * 1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_30 = MakeSnapshot(TestPAGSurface); - std::string md5 = DumpMD5(skImage_30); - - //第12帧 - TestPAGFile->setCurrentTime(12 * 1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_12 = MakeSnapshot(TestPAGSurface); - std::string secMd5 = DumpMD5(skImage_12); - - TestPAGFile->setDuration(TestPAGFile->duration() * 2); - - //第90帧 - TestPAGFile->setCurrentTime(4000000ll - 30 * 1000000ll / 30); - TestPAGPlayer->flush(); - auto skImage_90 = MakeSnapshot(TestPAGSurface); - std::string compMd5 = DumpMD5(skImage_90); - ASSERT_EQ(md5, compMd5); - TraceIf(skImage_30, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_30.png", md5 != compMd5); - TraceIf(skImage_90, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_90.png", md5 != compMd5); - - //第17帧 - //计算会有一定误差:现在的结果是10->10 13->11 17->12 - TestPAGFile->setCurrentTime(17 * 1000000ll / 30 + 1); - TestPAGPlayer->flush(); - auto skImage_17 = MakeSnapshot(TestPAGSurface); - std::string compSecMd5 = DumpMD5(skImage_17); - ASSERT_EQ(secMd5, compSecMd5); - TraceIf(skImage_12, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_12.png", - secMd5 != compSecMd5); - TraceIf(skImage_17, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_17.png", - secMd5 != compSecMd5); + //第30帧 + TestPAGFile->setCurrentTime(30 * 1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_30 = MakeSnapshot(TestPAGSurface); + std::string md5 = DumpMD5(skImage_30); + + //第12帧 + TestPAGFile->setCurrentTime(12 * 1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_12 = MakeSnapshot(TestPAGSurface); + std::string secMd5 = DumpMD5(skImage_12); + + TestPAGFile->setDuration(TestPAGFile->duration() * 2); + + //第90帧 + TestPAGFile->setCurrentTime(4000000ll - 30 * 1000000ll / 30); + TestPAGPlayer->flush(); + auto skImage_90 = MakeSnapshot(TestPAGSurface); + std::string compMd5 = DumpMD5(skImage_90); + ASSERT_EQ(md5, compMd5); + TraceIf(skImage_30, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_30.png", md5 != compMd5); + TraceIf(skImage_90, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_90.png", md5 != compMd5); + + //第17帧 + //计算会有一定误差:现在的结果是10->10 13->11 17->12 + TestPAGFile->setCurrentTime(17 * 1000000ll / 30 + 1); + TestPAGPlayer->flush(); + auto skImage_17 = MakeSnapshot(TestPAGSurface); + std::string compSecMd5 = DumpMD5(skImage_17); + ASSERT_EQ(secMd5, compSecMd5); + TraceIf(skImage_12, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_12.png", + secMd5 != compSecMd5); + TraceIf(skImage_17, "../test/out/test_repeat.pag_PAGFileTimeStretchScale_17.png", + secMd5 != compSecMd5); } /** * 用例描述: ImageFillRule编解码测试 */ PAG_TEST(PAGFileImageFillRuleCodec, ImageFillRuleCodec) { - auto testFile = PAGFile::Load("../resources/apitest/test_ImageFillRule.pag"); - EXPECT_NE(testFile, nullptr); - auto byteData = Codec::Encode(testFile->getFile()); - EXPECT_NE(byteData, nullptr); - EXPECT_NE(byteData->data(), nullptr); - EXPECT_NE(static_cast(byteData->length()), 0); + auto testFile = PAGFile::Load("../resources/apitest/test_ImageFillRule.pag"); + EXPECT_NE(testFile, nullptr); + auto byteData = Codec::Encode(testFile->getFile()); + EXPECT_NE(byteData, nullptr); + EXPECT_NE(byteData->data(), nullptr); + EXPECT_NE(static_cast(byteData->length()), 0); } /** * 用例描述: 竖排文本编解码测试 */ PAG_TEST(PAGFileTextDirectionCodec, TextDirectionCodec) { - auto testFile = PAGFile::Load("../resources/apitest/test_TextDirection.pag"); - EXPECT_NE(testFile, nullptr); - auto byteData = Codec::Encode(testFile->getFile()); - EXPECT_NE(byteData, nullptr); - EXPECT_NE(byteData->data(), nullptr); - EXPECT_NE(static_cast(byteData->length()), 0); + auto testFile = PAGFile::Load("../resources/apitest/test_TextDirection.pag"); + EXPECT_NE(testFile, nullptr); + auto byteData = Codec::Encode(testFile->getFile()); + EXPECT_NE(byteData, nullptr); + EXPECT_NE(byteData->data(), nullptr); + EXPECT_NE(static_cast(byteData->length()), 0); } /** * 用例描述: 竖排文本编解码测试 */ PAG_TEST(PAGFileVerticalTextCodec, VerticalTextCodec) { - auto testFile = PAGFile::Load("../resources/apitest/test_VerticalText.pag"); - EXPECT_NE(testFile, nullptr); - auto byteData = Codec::Encode(testFile->getFile()); - EXPECT_NE(byteData, nullptr); - EXPECT_NE(byteData->data(), nullptr); - EXPECT_NE(static_cast(byteData->length()), 0); + auto testFile = PAGFile::Load("../resources/apitest/test_VerticalText.pag"); + EXPECT_NE(testFile, nullptr); + auto byteData = Codec::Encode(testFile->getFile()); + EXPECT_NE(byteData, nullptr); + EXPECT_NE(byteData->data(), nullptr); + EXPECT_NE(static_cast(byteData->length()), 0); } /** * 用例描述: ShapeType测试 */ PAG_TEST_F(PAGFileBaseTest, ShapeType) { - auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); - EXPECT_NE(testFile, nullptr); - TestPAGPlayer->setComposition(testFile); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGFileTest"]["ShapeType"] = md5; + auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); + EXPECT_NE(testFile, nullptr); + TestPAGPlayer->setComposition(testFile); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGFileTest"]["ShapeType"] = md5; #ifdef COMPARE_JSON_PATH - auto cMd5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["ShapeType"]; - EXPECT_EQ(cMd5.get(), md5); + auto cMd5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["ShapeType"]; + EXPECT_EQ(cMd5.get(), md5); #endif } @@ -651,68 +651,68 @@ PAG_TEST_F(PAGFileBaseTest, ShapeType) { * 用例描述: ChildFrameToLocal接口测试,不改变时长 */ PAG_TEST_F(PAGFileBaseTest, ChildFrameToLocal) { - auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); - EXPECT_NE(testFile, nullptr); + auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); + EXPECT_NE(testFile, nullptr); - auto fileFrame = TimeToFrame(testFile->duration(), testFile->frameRate()); + auto fileFrame = TimeToFrame(testFile->duration(), testFile->frameRate()); - //超过fileDuration - auto result = testFile->childFrameToLocal(fileFrame + 10, testFile->frameRate()); - EXPECT_EQ(result, fileFrame + 10); + //超过fileDuration + auto result = testFile->childFrameToLocal(fileFrame + 10, testFile->frameRate()); + EXPECT_EQ(result, fileFrame + 10); - //少于0 - result = testFile->childFrameToLocal(-10, testFile->frameRate()); - EXPECT_EQ(result, -10); + //少于0 + result = testFile->childFrameToLocal(-10, testFile->frameRate()); + EXPECT_EQ(result, -10); - //处于0~fileDuration中 - result = testFile->childFrameToLocal(fileFrame - 10, testFile->frameRate()); - EXPECT_EQ(result, fileFrame - 10); + //处于0~fileDuration中 + result = testFile->childFrameToLocal(fileFrame - 10, testFile->frameRate()); + EXPECT_EQ(result, fileFrame - 10); } /** * 用例描述: ChildFrameToLocal进阶测试,改变时长 */ PAG_TEST_F(PAGFileBaseTest, ChildFrameToLocalAdvanced) { - auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); - EXPECT_NE(testFile, nullptr); - - auto fileFrame = TimeToFrame(testFile->duration(), testFile->frameRate()); - EXPECT_EQ(fileFrame, 336); - testFile->setDuration(FrameToTime(326, testFile->frameRate())); - - //超过fileDuration - auto result = testFile->childFrameToLocal(336, testFile->frameRate()); - EXPECT_EQ(result, 326); - - //少于0 - result = testFile->childFrameToLocal(-10, testFile->frameRate()); - EXPECT_EQ(result, -10); - - // scale情况 - //处于0~fileDuration中 - testFile->setTimeStretchMode(pag::PAGTimeStretchMode::Scale); - result = testFile->childFrameToLocal(316, testFile->frameRate()); - EXPECT_EQ(result, 306); - - //非scale情况 - testFile->setTimeStretchMode(pag::PAGTimeStretchMode::None); - result = testFile->childFrameToLocal(316, testFile->frameRate()); - EXPECT_EQ(result, 316); + auto testFile = PAGFile::Load("../resources/apitest/ShapeType.pag"); + EXPECT_NE(testFile, nullptr); + + auto fileFrame = TimeToFrame(testFile->duration(), testFile->frameRate()); + EXPECT_EQ(fileFrame, 336); + testFile->setDuration(FrameToTime(326, testFile->frameRate())); + + //超过fileDuration + auto result = testFile->childFrameToLocal(336, testFile->frameRate()); + EXPECT_EQ(result, 326); + + //少于0 + result = testFile->childFrameToLocal(-10, testFile->frameRate()); + EXPECT_EQ(result, -10); + + // scale情况 + //处于0~fileDuration中 + testFile->setTimeStretchMode(pag::PAGTimeStretchMode::Scale); + result = testFile->childFrameToLocal(316, testFile->frameRate()); + EXPECT_EQ(result, 306); + + //非scale情况 + testFile->setTimeStretchMode(pag::PAGTimeStretchMode::None); + result = testFile->childFrameToLocal(316, testFile->frameRate()); + EXPECT_EQ(result, 316); } /** * 用例描述: 测试椭圆转path,iOS14圆角badcase */ PAG_TEST_F(PAGFileBaseTest, EllipseToPath_ID80701969) { - auto pagFile = PAGFile::Load("../resources/apitest/ellipse_to_path.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGFileTest"]["EllipseToPath_ID80701969"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/ellipse_to_path.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGFileTest"]["EllipseToPath_ID80701969"] = md5; #ifdef COMPARE_JSON_PATH - auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["EllipseToPath_ID80701969"]; - EXPECT_EQ(audioMD5.get(), md5); + auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["EllipseToPath_ID80701969"]; + EXPECT_EQ(audioMD5.get(), md5); #endif } @@ -720,15 +720,15 @@ PAG_TEST_F(PAGFileBaseTest, EllipseToPath_ID80701969) { * 用例描述: 测试矩形转path,iOS14badcase */ PAG_TEST_F(PAGFileBaseTest, RectToPath_ID80703199) { - auto pagFile = PAGFile::Load("../resources/apitest/rect_to_path.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGFileTest"]["RectToPath_ID80703199"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/rect_to_path.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGFileTest"]["RectToPath_ID80703199"] = md5; #ifdef COMPARE_JSON_PATH - auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["RectToPath_ID80703199"]; - EXPECT_EQ(audioMD5.get(), md5); + auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["RectToPath_ID80703199"]; + EXPECT_EQ(audioMD5.get(), md5); #endif } @@ -736,15 +736,15 @@ PAG_TEST_F(PAGFileBaseTest, RectToPath_ID80703199) { * 用例描述: 测试圆角矩形转path,iOS14badCase */ PAG_TEST_F(PAGFileBaseTest, RoundRectToPath_ID80703201) { - auto pagFile = PAGFile::Load("../resources/apitest/round_rect_to_path.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGFileTest"]["RoundRectToPath_ID80703201"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/round_rect_to_path.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGFileTest"]["RoundRectToPath_ID80703201"] = md5; #ifdef COMPARE_JSON_PATH - auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["RoundRectToPath_ID80703201"]; - EXPECT_EQ(audioMD5.get(), md5); + auto audioMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["RoundRectToPath_ID80703201"]; + EXPECT_EQ(audioMD5.get(), md5); #endif } @@ -752,17 +752,17 @@ PAG_TEST_F(PAGFileBaseTest, RoundRectToPath_ID80703201) { * 用例描述: PAGFile设置开始时间 */ PAG_TEST_F(PAGFileBaseTest, SetStartTime) { - auto pagFile = PAGFile::Load("../assets/replacement.pag"); - TestPAGPlayer->setComposition(pagFile); - pagFile->setStartTime(2000000); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto skImage = MakeSnapshot(TestPAGSurface); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGFileTest"]["SetStartTime"] = md5; + auto pagFile = PAGFile::Load("../assets/replacement.pag"); + TestPAGPlayer->setComposition(pagFile); + pagFile->setStartTime(2000000); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto skImage = MakeSnapshot(TestPAGSurface); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGFileTest"]["SetStartTime"] = md5; #ifdef COMPARE_JSON_PATH - auto setStartTimeMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["SetStartTime"]; - EXPECT_EQ(setStartTimeMD5.get(), md5); + auto setStartTimeMD5 = PAGTestEnvironment::CompareJson["PAGFileTest"]["SetStartTime"]; + EXPECT_EQ(setStartTimeMD5.get(), md5); #endif } } // namespace pag diff --git a/test/PAGFilterTest.cpp b/test/PAGFilterTest.cpp index d8bd702c94..56fe215a1c 100644 --- a/test/PAGFilterTest.cpp +++ b/test/PAGFilterTest.cpp @@ -30,601 +30,601 @@ PAG_TEST_CASE(PAGFilterTest) * 用例描述: CornerPin用例 */ PAG_TEST(PAGFilterTest, CornerPin_ID79157693) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/cornerpin.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/cornerpin.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["cornerpin"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_cornerpin_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["cornerpin"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_cornerpin_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["cornerpin"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["cornerpin"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: Bulge效果测试 */ PAG_TEST(PAGFilterTest, Bulge_ID79159683) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/bulge.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(300000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/bulge.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(300000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["bulge"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_bulge_test_300000.png", cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["bulge"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_bulge_test_300000.png", cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["bulge"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["bulge"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: MotionTile效果测试 */ PAG_TEST(PAGFilterTest, MotionTile_ID79162339) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/motiontile.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - auto md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/motiontile.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + auto md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["motiontile"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_motiontile_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["motiontile"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_motiontile_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["motiontile"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["motiontile"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: MotionBlur效果测试 */ PAG_TEST(PAGFilterTest, MotionBlur_ID79162447) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/MotionBlur.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(200000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - auto md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/MotionBlur.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(200000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + auto md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["motionblur_scale"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_motionblur_test_200000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["motionblur_scale"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_motionblur_test_200000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["motionblur_scale"] = md5; - - pagFile->setCurrentTime(600000); - pagPlayer->flush(); - snapshot = MakeSnapshot(pagSurface); - md5 = DumpMD5(snapshot); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["motionblur_scale"] = md5; + + pagFile->setCurrentTime(600000); + pagPlayer->flush(); + snapshot = MakeSnapshot(pagSurface); + md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - cJson = compareJson["PAGFilterTest"]["motionblur_translate"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_motionblur_test_600000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + cJson = compareJson["PAGFilterTest"]["motionblur_translate"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_motionblur_test_600000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - dumpJson["PAGFilterTest"]["motionblur_translate"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + dumpJson["PAGFilterTest"]["motionblur_translate"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: GaussBlur效果测试 */ PAG_TEST(PAGFilterTest, GaussBlur_ID79162977) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/fastblur.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/fastblur.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["gaussblur"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_gaussblur_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["gaussblur"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_gaussblur_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["gaussblur"] = md5; - - pagFile = PAGFile::Load("../resources/filter/fastblur_norepeat.pag"); - ASSERT_NE(pagFile, nullptr); - pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - snapshot = MakeSnapshot(pagSurface); - md5 = DumpMD5(snapshot); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["gaussblur"] = md5; + + pagFile = PAGFile::Load("../resources/filter/fastblur_norepeat.pag"); + ASSERT_NE(pagFile, nullptr); + pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + snapshot = MakeSnapshot(pagSurface); + md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - cJson = compareJson["PAGFilterTest"]["gaussblur_norepeat"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_gaussblur_norepeat_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + cJson = compareJson["PAGFilterTest"]["gaussblur_norepeat"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_gaussblur_norepeat_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - dumpJson["PAGFilterTest"]["gaussblur_norepeat"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + dumpJson["PAGFilterTest"]["gaussblur_norepeat"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: Glow效果测试 */ PAG_TEST(PAGFilterTest, Glow_ID79163671) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/Glow.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(200000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/Glow.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(200000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["glow"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_glow_test_200000.png", cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["glow"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_glow_test_200000.png", cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["glow"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["glow"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: DropShadow效果测试 */ PAG_TEST(PAGFilterTest, DropShadow_ID79164133) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/DropShadow.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/DropShadow.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["dropshadow"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_dropshadow_test_200000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["dropshadow"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_dropshadow_test_200000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["dropshadow"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["dropshadow"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: DisplacementMap */ PAG_TEST(PAGFilterTest, DisplacementMap_ID79234919) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/DisplacementMap.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(600000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/DisplacementMap.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(600000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["displacementmap"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_displacementmap_test_600000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["displacementmap"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_displacementmap_test_600000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["displacementmap"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["displacementmap"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: DisplacementMap特殊用例测试,包含:缩放,模糊 */ PAG_TEST(PAGFilterTest, DisplacementMap_ID82637265) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/displement_map_video_scale.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(3632520); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/displement_map_video_scale.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(3632520); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["displacementmap_video_scale"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/displacementmap_video_scale_3632520.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["displacementmap_video_scale"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/displacementmap_video_scale_3632520.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["displacementmap_video_scale"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["displacementmap_video_scale"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: GaussBlur_Static */ PAG_TEST(PAGFilterTest, GaussBlur_Static) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/GaussBlur_Static.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(0); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/GaussBlur_Static.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(0); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["gaussblur_static"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/gaussblur_static.png", cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["gaussblur_static"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/gaussblur_static.png", cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["gaussblur_static"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["gaussblur_static"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: RadialBlur */ PAG_TEST(PAGFilterTest, RadialBlur) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/RadialBlur.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/RadialBlur.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["radialblur"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_radialblur_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["radialblur"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_radialblur_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["radialblur"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["radialblur"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: Mosaic */ PAG_TEST(PAGFilterTest, Mosaic) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/MosaicChange.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(0); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/MosaicChange.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(0); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["mosaic"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_mosaic_test_1000000.png", cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["mosaic"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_mosaic_test_1000000.png", cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["mosaic"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["mosaic"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } /** * 用例描述: 多滤镜混合效果测试 */ PAG_TEST(PAGFilterTest, MultiFilter_ID79164477) { - json compareJson; - std::ifstream inputFile("../test/res/compare_filter_md5.json"); - if (inputFile) { - inputFile >> compareJson; - inputFile.close(); - } - auto pagFile = PAGFile::Load("../resources/filter/cornerpin-bulge.pag"); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(1000000); - pagPlayer->flush(); - auto snapshot = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(snapshot); + json compareJson; + std::ifstream inputFile("../test/res/compare_filter_md5.json"); + if (inputFile) { + inputFile >> compareJson; + inputFile.close(); + } + auto pagFile = PAGFile::Load("../resources/filter/cornerpin-bulge.pag"); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(1000000); + pagPlayer->flush(); + auto snapshot = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - auto cJson = compareJson["PAGFilterTest"]["cornerpin-bulge"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_cornerpin_bulge_test_1000000.png", - cJson.get() != md5); - EXPECT_EQ(cJson.get(), md5); - } + auto cJson = compareJson["PAGFilterTest"]["cornerpin-bulge"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_cornerpin_bulge_test_1000000.png", + cJson.get() != md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - json dumpJson; - std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); - if (dumpInputFile) { - dumpInputFile >> dumpJson; - dumpInputFile.close(); - } - dumpJson["PAGFilterTest"]["cornerpin-bulge"] = md5; - - pagFile = PAGFile::Load("../resources/filter/motiontile_blur.pag"); - ASSERT_NE(pagFile, nullptr); - pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - pagFile->setCurrentTime(400000); - pagPlayer->flush(); - snapshot = MakeSnapshot(pagSurface); - md5 = DumpMD5(snapshot); + json dumpJson; + std::ifstream dumpInputFile("../test/out/compare_filter_md5.json"); + if (dumpInputFile) { + dumpInputFile >> dumpJson; + dumpInputFile.close(); + } + dumpJson["PAGFilterTest"]["cornerpin-bulge"] = md5; + + pagFile = PAGFile::Load("../resources/filter/motiontile_blur.pag"); + ASSERT_NE(pagFile, nullptr); + pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + pagFile->setCurrentTime(400000); + pagPlayer->flush(); + snapshot = MakeSnapshot(pagSurface); + md5 = DumpMD5(snapshot); #ifdef COMPARE_JSON_PATH - cJson = compareJson["PAGFilterTest"]["motiontile_blur"]; - if (cJson != nullptr) { - TraceIf(snapshot, "../test/out/pag_motiontile_blur_test_400000.png", - cJson.get() == md5); - EXPECT_EQ(cJson.get(), md5); - } + cJson = compareJson["PAGFilterTest"]["motiontile_blur"]; + if (cJson != nullptr) { + TraceIf(snapshot, "../test/out/pag_motiontile_blur_test_400000.png", + cJson.get() == md5); + EXPECT_EQ(cJson.get(), md5); + } #endif - dumpJson["PAGFilterTest"]["motiontile_blur"] = md5; - std::ofstream outFile("../test/out/compare_filter_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + dumpJson["PAGFilterTest"]["motiontile_blur"] = md5; + std::ofstream outFile("../test/out/compare_filter_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } } // namespace pag diff --git a/test/PAGFontTest.cpp b/test/PAGFontTest.cpp index 7bbc2d3f99..f288d6221a 100644 --- a/test/PAGFontTest.cpp +++ b/test/PAGFontTest.cpp @@ -30,62 +30,62 @@ using nlohmann::json; * 用例描述: 字体相关功能测试 */ PAG_TEST(PAGFontTest, TestFont) { - json dumpJson; - json compareJson; - std::ifstream inputFile("../test/res/compare_font_md5.json"); - bool needCompare = false; - if (inputFile) { - needCompare = true; - inputFile >> compareJson; - } + json dumpJson; + json compareJson; + std::ifstream inputFile("../test/res/compare_font_md5.json"); + bool needCompare = false; + if (inputFile) { + needCompare = true; + inputFile >> compareJson; + } - std::vector compareVector; - std::string fileName = "test_font"; - if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { - compareVector = compareJson[fileName].get>(); - } + std::vector compareVector; + std::string fileName = "test_font"; + if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { + compareVector = compareJson[fileName].get>(); + } - PAGFont::RegisterFont("../resources/font/NotoSerifSC-Regular.otf", 0, "TTTGBMedium", "Regular"); - auto TestPAGFile = PAGFile::Load("../resources/apitest/test_font.pag"); - ASSERT_NE(TestPAGFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(TestPAGFile); + PAGFont::RegisterFont("../resources/font/NotoSerifSC-Regular.otf", 0, "TTTGBMedium", "Regular"); + auto TestPAGFile = PAGFile::Load("../resources/apitest/test_font.pag"); + ASSERT_NE(TestPAGFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(TestPAGFile); - Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); - Frame currentFrame = 0; + Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); + Frame currentFrame = 0; - std::vector md5Vector; - std::string errorMsg; + std::vector md5Vector; + std::string errorMsg; - bool status = true; - while (currentFrame < totalFrames) { - //添加0.1帧目的是保证progress不会由于精度问题帧数计算错误,frame应该使用totalFrames作为总体帧数。因为对于file来说总时长为[0,totalFrames],对应于[0,1],因此归一化时,分母应该为totalFrames - pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); - pagPlayer->flush(); + bool status = true; + while (currentFrame < totalFrames) { + //添加0.1帧目的是保证progress不会由于精度问题帧数计算错误,frame应该使用totalFrames作为总体帧数。因为对于file来说总时长为[0,totalFrames],对应于[0,1],因此归一化时,分母应该为totalFrames + pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); + pagPlayer->flush(); - auto skImage = MakeSnapshot(pagSurface); + auto skImage = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(skImage); - md5Vector.push_back(md5); - if (needCompare && compareVector[currentFrame] != md5) { - errorMsg += (std::to_string(currentFrame) + ";"); - if (status) { - std::string imagePath = - "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; - Trace(skImage, imagePath); - status = false; - } + std::string md5 = DumpMD5(skImage); + md5Vector.push_back(md5); + if (needCompare && compareVector[currentFrame] != md5) { + errorMsg += (std::to_string(currentFrame) + ";"); + if (status) { + std::string imagePath = + "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; + Trace(skImage, imagePath); + status = false; + } + } + currentFrame++; } - currentFrame++; - } - EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; - dumpJson[fileName] = md5Vector; - std::ofstream outFile("../test/out/compare_font_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; + dumpJson[fileName] = md5Vector; + std::ofstream outFile("../test/out/compare_font_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } } // namespace pag diff --git a/test/PAGGradientColorTest.cpp b/test/PAGGradientColorTest.cpp index 4107da8cd0..d570221787 100644 --- a/test/PAGGradientColorTest.cpp +++ b/test/PAGGradientColorTest.cpp @@ -27,24 +27,24 @@ PAG_TEST_CASE(PAGGradientColorTest) * 用例描述: 渐变 */ PAG_TEST_F(PAGGradientColorTest, GradientColor_ID84028439) { - std::vector files; - GetAllPAGFiles("../resources/gradient", files); - for (auto& file : files) { - auto pagFile = PAGFile::Load(file); - EXPECT_NE(pagFile, nullptr); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.5); - TestPAGPlayer->flush(); - auto md5 = DumpMD5(TestPAGSurface); - auto found = file.find_last_of("/\\"); - auto fileName = file.substr(found + 1); - PAGTestEnvironment::DumpJson["PAGGradientColorTest"][fileName] = md5; + std::vector files; + GetAllPAGFiles("../resources/gradient", files); + for (auto& file : files) { + auto pagFile = PAGFile::Load(file); + EXPECT_NE(pagFile, nullptr); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.5); + TestPAGPlayer->flush(); + auto md5 = DumpMD5(TestPAGSurface); + auto found = file.find_last_of("/\\"); + auto fileName = file.substr(found + 1); + PAGTestEnvironment::DumpJson["PAGGradientColorTest"][fileName] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGGradientColorTest"][fileName]; - auto path = "../test/out/gradient_" + fileName + ".png"; - TraceIf(TestPAGSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGGradientColorTest"][fileName]; + auto path = "../test/out/gradient_" + fileName + ".png"; + TraceIf(TestPAGSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - } + } } } // namespace pag diff --git a/test/PAGImageLayerTest.cpp b/test/PAGImageLayerTest.cpp index 1cdf9601c5..b3adbc479a 100644 --- a/test/PAGImageLayerTest.cpp +++ b/test/PAGImageLayerTest.cpp @@ -31,57 +31,57 @@ PAG_TEST_SUIT(PAGImageLayerTest) * 用例描述: PAGImageLayer 图层基础边缘 Case 测试 */ PAG_TEST_F(PAGImageLayerTest, imageBasetTest) { - int target = 0; - std::shared_ptr imageLayer = - std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); - ASSERT_NE(imageLayer, nullptr); - auto file = PAGImage::FromPath("../test/res/compare_dump.json"); - auto pag = PAGImage::FromPath("../resources/apitest/test.pag"); - // 非法文件都无法被decode成PAGImage,file是nullptr - imageLayer->replaceImage(file); - imageLayer->replaceImage(pag); - imageLayer->replaceImage(nullptr); + int target = 0; + std::shared_ptr imageLayer = + std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); + ASSERT_NE(imageLayer, nullptr); + auto file = PAGImage::FromPath("../test/res/compare_dump.json"); + auto pag = PAGImage::FromPath("../resources/apitest/test.pag"); + // 非法文件都无法被decode成PAGImage,file是nullptr + imageLayer->replaceImage(file); + imageLayer->replaceImage(pag); + imageLayer->replaceImage(nullptr); } /** * 用例描述: PAGImageLayer多线程替换测试 */ PAG_TEST_F(PAGImageLayerTest, imageMultiThreadReplace) { - int target = 0; - std::shared_ptr imageLayer = - std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); - ASSERT_NE(imageLayer, nullptr); - ASSERT_EQ(imageLayer->editableIndex(), 1); - ASSERT_EQ(imageLayer->contentDuration(), 2 * 1000000); - auto image = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); + int target = 0; + std::shared_ptr imageLayer = + std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); + ASSERT_NE(imageLayer, nullptr); + ASSERT_EQ(imageLayer->editableIndex(), 1); + ASSERT_EQ(imageLayer->contentDuration(), 2 * 1000000); + auto image = PAGImage::FromPath("../resources/apitest/imageReplacement.png"); - TestPAGFile->setCurrentTime(3000000); - TestPAGPlayer->flush(); - // 多线程同时替换图片 - std::thread thread1([imageLayer, image]() { - for (int i = 0; i < 10; ++i) { - std::cout << "线程1 present" << std::endl; - TestPAGPlayer->flush(); - } - }); - std::thread thread2([imageLayer, image]() { - for (int i = 0; i < 10; ++i) { - std::cout << "线程2 替换图片" << std::endl; - imageLayer->replaceImage(image); - TestPAGPlayer->flush(); - } - }); - thread1.join(); - thread2.join(); + TestPAGFile->setCurrentTime(3000000); + TestPAGPlayer->flush(); + // 多线程同时替换图片 + std::thread thread1([imageLayer, image]() { + for (int i = 0; i < 10; ++i) { + std::cout << "线程1 present" << std::endl; + TestPAGPlayer->flush(); + } + }); + std::thread thread2([imageLayer, image]() { + for (int i = 0; i < 10; ++i) { + std::cout << "线程2 替换图片" << std::endl; + imageLayer->replaceImage(image); + TestPAGPlayer->flush(); + } + }); + thread1.join(); + thread2.join(); - imageLayer->replaceImage(image); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - json imageLayerJson = {{"image", md5}}; - PAGTestEnvironment::DumpJson["PAGImageLayerTest"] = imageLayerJson; + imageLayer->replaceImage(image); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + json imageLayerJson = {{"image", md5}}; + PAGTestEnvironment::DumpJson["PAGImageLayerTest"] = imageLayerJson; #ifdef COMPARE_JSON_PATH - auto cJson = PAGTestEnvironment::CompareJson["PAGImageLayerTest"]["image"]; - ASSERT_EQ(cJson.get(), md5); + auto cJson = PAGTestEnvironment::CompareJson["PAGImageLayerTest"]["image"]; + ASSERT_EQ(cJson.get(), md5); #endif } @@ -89,44 +89,44 @@ PAG_TEST_F(PAGImageLayerTest, imageMultiThreadReplace) { * 用例描述: PAGImageLayerContentDuration获取测试 */ PAG_TEST_F(PAGImageLayerTest, imageLayerContentDuration) { - auto testFile = PAGFile::Load("../resources/apitest/test_TimeRemapInFileRange.pag"); - // 图层 timeremap 没有超过文件显示区域 - int commonTarget = 4; - std::shared_ptr imageLayer = - std::static_pointer_cast(GetLayer(testFile, LayerType::Image, commonTarget)); - ASSERT_NE(imageLayer, nullptr); - ASSERT_EQ(imageLayer->contentDuration(), 1160000); + auto testFile = PAGFile::Load("../resources/apitest/test_TimeRemapInFileRange.pag"); + // 图层 timeremap 没有超过文件显示区域 + int commonTarget = 4; + std::shared_ptr imageLayer = + std::static_pointer_cast(GetLayer(testFile, LayerType::Image, commonTarget)); + ASSERT_NE(imageLayer, nullptr); + ASSERT_EQ(imageLayer->contentDuration(), 1160000); - testFile = PAGFile::Load("../resources/apitest/test_TimeRemapBeyondFileRange.pag"); - // 图层 timeremap 都超过了文件显示区域 - imageLayer = - std::static_pointer_cast(GetLayer(testFile, LayerType::Image, commonTarget)); - ASSERT_NE(imageLayer, nullptr); - ASSERT_EQ(imageLayer->contentDuration(), 240000); + testFile = PAGFile::Load("../resources/apitest/test_TimeRemapBeyondFileRange.pag"); + // 图层 timeremap 都超过了文件显示区域 + imageLayer = + std::static_pointer_cast(GetLayer(testFile, LayerType::Image, commonTarget)); + ASSERT_NE(imageLayer, nullptr); + ASSERT_EQ(imageLayer->contentDuration(), 240000); - // 变速timeremap测试用例 - testFile = PAGFile::Load("../resources/apitest/timeRemap_shift.pag"); - auto pagComposition = PAGComposition::Make(testFile->width(), testFile->height()); - auto pagImageLayer = std::static_pointer_cast(testFile->getLayerAt(0)); - pagComposition->addLayer(pagImageLayer); - imageLayer = std::static_pointer_cast(pagComposition->getLayerAt(0)); - ASSERT_NE(imageLayer, nullptr); - ASSERT_EQ(imageLayer->contentDuration(), 4000000); + // 变速timeremap测试用例 + testFile = PAGFile::Load("../resources/apitest/timeRemap_shift.pag"); + auto pagComposition = PAGComposition::Make(testFile->width(), testFile->height()); + auto pagImageLayer = std::static_pointer_cast(testFile->getLayerAt(0)); + pagComposition->addLayer(pagImageLayer); + imageLayer = std::static_pointer_cast(pagComposition->getLayerAt(0)); + ASSERT_NE(imageLayer, nullptr); + ASSERT_EQ(imageLayer->contentDuration(), 4000000); } /** * 用例描述: PAGImageLayer getBounds接口 测试 */ PAG_TEST_F(PAGImageLayerTest, getBoundsTest) { - auto pagFile = pag::PAGFile::Load("../resources/apitest/ImageLayerBounds.pag"); - Rect rect1 = Rect::MakeXYWH(0, 0, 720, 1280); - Rect rect2 = Rect::MakeXYWH(0, 0, 720, 720); - Rect rect3 = Rect::MakeXYWH(0, 0, 720, 1280); - Rect bounds[] = {rect1, rect2, rect3}; - for (int i = 0; i < pagFile->numImages(); i++) { - auto pagImageLayer = pagFile->getLayersByEditableIndex(i, pag::LayerType::Image)[0]; - auto rect = pagImageLayer->getBounds(); - ASSERT_EQ(rect, bounds[i]); - } + auto pagFile = pag::PAGFile::Load("../resources/apitest/ImageLayerBounds.pag"); + Rect rect1 = Rect::MakeXYWH(0, 0, 720, 1280); + Rect rect2 = Rect::MakeXYWH(0, 0, 720, 720); + Rect rect3 = Rect::MakeXYWH(0, 0, 720, 1280); + Rect bounds[] = {rect1, rect2, rect3}; + for (int i = 0; i < pagFile->numImages(); i++) { + auto pagImageLayer = pagFile->getLayersByEditableIndex(i, pag::LayerType::Image)[0]; + auto rect = pagImageLayer->getBounds(); + ASSERT_EQ(rect, bounds[i]); + } } } // namespace pag diff --git a/test/PAGImageTest.cpp b/test/PAGImageTest.cpp index ee5b56233e..22774f532a 100644 --- a/test/PAGImageTest.cpp +++ b/test/PAGImageTest.cpp @@ -33,51 +33,51 @@ PAG_TEST_SUIT(PAGImageTest) * 用例描述: PAGImage contentDuration 接口 */ PAG_TEST_F(PAGImageTest, contentDuration) { - int target = 0; - std::shared_ptr imageLayer = - std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); - ASSERT_EQ(imageLayer->contentDuration(), 2 * 1000000); + int target = 0; + std::shared_ptr imageLayer = + std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); + ASSERT_EQ(imageLayer->contentDuration(), 2 * 1000000); } /** * 用例描述: PAGImage解码等功能 */ PAG_TEST_F(PAGImageTest, image) { - int target = 0; - std::shared_ptr imageLayer = - std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); - ASSERT_NE(imageLayer, nullptr); - ASSERT_EQ(imageLayer->editableIndex(), 1); - int width = 110; - int height = 110; - size_t rowBytes = 110 * 4; - auto fileData = ByteData::FromPath("../resources/apitest/data.rgba"); - Bitmap bitmap = {}; - auto result = bitmap.allocPixels(0, height); - ASSERT_EQ(result, false); - result = bitmap.allocPixels(width, height, true); - ASSERT_EQ(result, true); - EXPECT_EQ(bitmap.colorType(), ColorType::ALPHA_8); - result = bitmap.allocPixels(width, height); - ASSERT_EQ(result, true); - auto info = - ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Premultiplied, rowBytes); - bitmap.writePixels(info, fileData->data()); - auto newFileData = ByteData::Make(fileData->length()); - bitmap.readPixels(info, newFileData->data()); - auto compare = memcmp(fileData->data(), newFileData->data(), fileData->length()); - ASSERT_EQ(compare, 0); - auto image = PAGImage::FromPixels(fileData->data(), width, height, rowBytes, ColorType::RGBA_8888, - AlphaType::Premultiplied); - TestPAGFile->setCurrentTime(3000000); - imageLayer->replaceImage(image); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - json imageLayerJson = {{"image", md5}}; - PAGTestEnvironment::DumpJson["PAGImageTest"] = imageLayerJson; + int target = 0; + std::shared_ptr imageLayer = + std::static_pointer_cast(GetLayer(TestPAGFile, LayerType::Image, target)); + ASSERT_NE(imageLayer, nullptr); + ASSERT_EQ(imageLayer->editableIndex(), 1); + int width = 110; + int height = 110; + size_t rowBytes = 110 * 4; + auto fileData = ByteData::FromPath("../resources/apitest/data.rgba"); + Bitmap bitmap = {}; + auto result = bitmap.allocPixels(0, height); + ASSERT_EQ(result, false); + result = bitmap.allocPixels(width, height, true); + ASSERT_EQ(result, true); + EXPECT_EQ(bitmap.colorType(), ColorType::ALPHA_8); + result = bitmap.allocPixels(width, height); + ASSERT_EQ(result, true); + auto info = + ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Premultiplied, rowBytes); + bitmap.writePixels(info, fileData->data()); + auto newFileData = ByteData::Make(fileData->length()); + bitmap.readPixels(info, newFileData->data()); + auto compare = memcmp(fileData->data(), newFileData->data(), fileData->length()); + ASSERT_EQ(compare, 0); + auto image = PAGImage::FromPixels(fileData->data(), width, height, rowBytes, ColorType::RGBA_8888, + AlphaType::Premultiplied); + TestPAGFile->setCurrentTime(3000000); + imageLayer->replaceImage(image); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + json imageLayerJson = {{"image", md5}}; + PAGTestEnvironment::DumpJson["PAGImageTest"] = imageLayerJson; #ifdef COMPARE_JSON_PATH - auto cJson = PAGTestEnvironment::CompareJson["PAGImageTest"]["image"]; - ASSERT_EQ(cJson.get(), md5); + auto cJson = PAGTestEnvironment::CompareJson["PAGImageTest"]["image"]; + ASSERT_EQ(cJson.get(), md5); #endif } @@ -85,27 +85,27 @@ PAG_TEST_F(PAGImageTest, image) { * 用例描述: PAGImage解码等功能 */ PAG_TEST_F(PAGImageTest, image2) { - auto image = Image::MakeFrom("../resources/apitest/imageReplacement.png"); - ASSERT_TRUE(image != nullptr); - ASSERT_EQ(image->height(), 110); - ASSERT_EQ(image->width(), 110); - ASSERT_EQ(image->height(), 110); - ASSERT_EQ(image->orientation(), Orientation::TopLeft); - Bitmap bitmap = {}; - auto result = bitmap.allocPixels(image->width(), image->height()); - ASSERT_TRUE(result); - auto pixels = bitmap.lockPixels(); - result = image->readPixels(bitmap.info(), pixels); - bitmap.unlockPixels(); - ASSERT_TRUE(result); + auto image = Image::MakeFrom("../resources/apitest/imageReplacement.png"); + ASSERT_TRUE(image != nullptr); + ASSERT_EQ(image->height(), 110); + ASSERT_EQ(image->width(), 110); + ASSERT_EQ(image->height(), 110); + ASSERT_EQ(image->orientation(), Orientation::TopLeft); + Bitmap bitmap = {}; + auto result = bitmap.allocPixels(image->width(), image->height()); + ASSERT_TRUE(result); + auto pixels = bitmap.lockPixels(); + result = image->readPixels(bitmap.info(), pixels); + bitmap.unlockPixels(); + ASSERT_TRUE(result); - auto md5 = DumpMD5(bitmap); - json imageLayerJson = {{"image", md5}}; - PAGTestEnvironment::DumpJson["PAGImageTester"] = imageLayerJson; + auto md5 = DumpMD5(bitmap); + json imageLayerJson = {{"image", md5}}; + PAGTestEnvironment::DumpJson["PAGImageTester"] = imageLayerJson; #ifdef COMPARE_JSON_PATH - auto cJson = PAGTestEnvironment::CompareJson["PAGImageTester"]["image"]; - TraceIf(bitmap, "../test/out/PAGImageTester_image.png", md5 != cJson.get()); - ASSERT_EQ(cJson.get(), md5); + auto cJson = PAGTestEnvironment::CompareJson["PAGImageTester"]["image"]; + TraceIf(bitmap, "../test/out/PAGImageTester_image.png", md5 != cJson.get()); + ASSERT_EQ(cJson.get(), md5); #endif } @@ -113,26 +113,26 @@ PAG_TEST_F(PAGImageTest, image2) { * 用例描述: 带旋转图片PAGImage解码等功能 */ PAG_TEST_F(PAGImageTest, image3) { - auto pagImage = PAGImage::FromPath("../resources/apitest/rotation.jpg"); - ASSERT_TRUE(pagImage != nullptr); - EXPECT_EQ(pagImage->width(), 3024); - EXPECT_EQ(pagImage->height(), 4032); - auto pagFile = PAGFile::Load("../resources/apitest/replace2.pag"); - ASSERT_TRUE(pagFile != nullptr); - pagFile->replaceImage(0, pagImage); - auto surface = PAGSurface::MakeOffscreen(720, 720); - ASSERT_TRUE(surface != nullptr); - auto player = new PAGPlayer(); - player->setComposition(pagFile); - player->setSurface(surface); - auto result = player->flush(); - EXPECT_TRUE(result); - auto md5 = DumpMD5(surface); - PAGTestEnvironment::DumpJson["PAGImageDecodeTest"]["image_rotation"] = md5; + auto pagImage = PAGImage::FromPath("../resources/apitest/rotation.jpg"); + ASSERT_TRUE(pagImage != nullptr); + EXPECT_EQ(pagImage->width(), 3024); + EXPECT_EQ(pagImage->height(), 4032); + auto pagFile = PAGFile::Load("../resources/apitest/replace2.pag"); + ASSERT_TRUE(pagFile != nullptr); + pagFile->replaceImage(0, pagImage); + auto surface = PAGSurface::MakeOffscreen(720, 720); + ASSERT_TRUE(surface != nullptr); + auto player = new PAGPlayer(); + player->setComposition(pagFile); + player->setSurface(surface); + auto result = player->flush(); + EXPECT_TRUE(result); + auto md5 = DumpMD5(surface); + PAGTestEnvironment::DumpJson["PAGImageDecodeTest"]["image_rotation"] = md5; #ifdef COMPARE_JSON_PATH - auto cJson = PAGTestEnvironment::CompareJson["PAGImageDecodeTest"]["image_rotation"]; - TraceIf(surface, "../test/out/test_image_rotation.png", md5 != cJson.get()); - ASSERT_EQ(cJson.get(), md5); + auto cJson = PAGTestEnvironment::CompareJson["PAGImageDecodeTest"]["image_rotation"]; + TraceIf(surface, "../test/out/test_image_rotation.png", md5 != cJson.get()); + ASSERT_EQ(cJson.get(), md5); #endif } } // namespace pag diff --git a/test/PAGLayerTest.cpp b/test/PAGLayerTest.cpp index e8bc137fb8..9bb7556f5c 100644 --- a/test/PAGLayerTest.cpp +++ b/test/PAGLayerTest.cpp @@ -31,128 +31,128 @@ PAG_TEST_CASE(PAGLayerTest) * 用例描述: PAGLayerTest 测试获取layerName接口,正确返回PAGSolidLayer */ PAG_TEST_F(PAGLayerTest, layerName) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - ASSERT_NE(layer, nullptr); - ASSERT_EQ(layer->layerName(), "PAGSolidLayer"); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + ASSERT_NE(layer, nullptr); + ASSERT_EQ(layer->layerName(), "PAGSolidLayer"); } /** * 用例描述: PAGLayerTest 测试frameRate准确性,正确为25 */ PAG_TEST_F(PAGLayerTest, frameRate) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - ASSERT_NE(layer, nullptr); - ASSERT_EQ(layer->frameRate(), 25); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + ASSERT_NE(layer, nullptr); + ASSERT_EQ(layer->frameRate(), 25); } /** * 用例描述: PAGLayerTest 测试获取startTime接口的准确性,正确为13 * 1000000 / 25 */ PAG_TEST_F(PAGLayerTest, startTime) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - ASSERT_NE(layer, nullptr); - ASSERT_EQ(layer->startTime(), 13 * 1000000 / 25); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + ASSERT_NE(layer, nullptr); + ASSERT_EQ(layer->startTime(), 13 * 1000000 / 25); } /** * 用例描述: PAGLayerTest 测试获取pag的duration接口,正确为10 * 1000000 - 13 * 1000000 / 25 */ PAG_TEST_F(PAGLayerTest, duration) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - ASSERT_EQ(layer->duration(), 10 * 1000000 - 13 * 1000000 / 25); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + ASSERT_EQ(layer->duration(), 10 * 1000000 - 13 * 1000000 / 25); } /** * 用例描述: PAGLayerTest测试trackMatteLayer图层是否正常 */ PAG_TEST_F(PAGLayerTest, trackMatteLayer) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - auto trackMatteLayer = layer->trackMatteLayer(); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + auto trackMatteLayer = layer->trackMatteLayer(); - ASSERT_NE(trackMatteLayer, nullptr); - ASSERT_EQ(trackMatteLayer->layerName(), "TrackMatteLayer"); + ASSERT_NE(trackMatteLayer, nullptr); + ASSERT_EQ(trackMatteLayer->layerName(), "TrackMatteLayer"); } /** * 用例描述: PAGLayerTest测试parent接口是否正确,正确为RootLayer */ PAG_TEST_F(PAGLayerTest, parent) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - auto parent = layer->parent(); - ASSERT_NE(parent, nullptr); - ASSERT_EQ(parent->layerName(), "RootLayer"); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + auto parent = layer->parent(); + ASSERT_NE(parent, nullptr); + ASSERT_EQ(parent->layerName(), "RootLayer"); } /** * 用例描述: PAGLayerTest测试local global时间转换接口 */ PAG_TEST_F(PAGLayerTest, localGlobalConvert) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - auto parent = layer->parent(); - ASSERT_NE(parent, nullptr); - ASSERT_EQ(parent->layerName(), "RootLayer"); - ASSERT_EQ(layer->localTimeToGlobal(0), 0); - ASSERT_EQ(layer->globalToLocalTime(520 * 1000), 520 * 1000); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + auto parent = layer->parent(); + ASSERT_NE(parent, nullptr); + ASSERT_EQ(parent->layerName(), "RootLayer"); + ASSERT_EQ(layer->localTimeToGlobal(0), 0); + ASSERT_EQ(layer->globalToLocalTime(520 * 1000), 520 * 1000); } /** * 用例描述: PAGLayerTest测试bounds接口,正确返回(0, 0, 720, 1080) */ PAG_TEST_F(PAGLayerTest, bounds) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - auto bounds = layer->getBounds(); - auto cBounds = Rect::MakeLTRB(0, 0, 720, 1080); - ASSERT_TRUE(bounds == cBounds); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + auto bounds = layer->getBounds(); + auto cBounds = Rect::MakeLTRB(0, 0, 720, 1080); + ASSERT_TRUE(bounds == cBounds); } /** * 用例描述: PAGLayerTest测试markers接口,确保marker准确 */ PAG_TEST_F(PAGLayerTest, markers) { - int target = 0; - // from 0.52s-10s - auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); - auto markers = layer->markers(); - ASSERT_TRUE(markers.size() == 2); - ASSERT_EQ(markers[0]->startTime, 125); - ASSERT_EQ(markers[0]->duration, 0); - ASSERT_EQ(markers[0]->comment, "1"); - ASSERT_EQ(markers[1]->startTime, 150); - ASSERT_EQ(markers[1]->duration, 0); - ASSERT_EQ(markers[1]->comment, "2"); + int target = 0; + // from 0.52s-10s + auto layer = GetLayer(TestPAGFile, LayerType::Solid, target); + auto markers = layer->markers(); + ASSERT_TRUE(markers.size() == 2); + ASSERT_EQ(markers[0]->startTime, 125); + ASSERT_EQ(markers[0]->duration, 0); + ASSERT_EQ(markers[0]->comment, "1"); + ASSERT_EQ(markers[1]->startTime, 150); + ASSERT_EQ(markers[1]->duration, 0); + ASSERT_EQ(markers[1]->comment, "2"); } /** * 用例描述: PAGLayerTest测试trackMatte接口,对比获取到的MD5 */ PAG_TEST_F(PAGLayerTest, trackMatte) { - // from 0.52s-10s - TestPAGFile->setCurrentTime(800 * 1000); - ASSERT_EQ(TestPAGFile->currentTime(), 800 * 1000); - TestPAGPlayer->flush(); - auto tmMd5 = getMd5FromSnap(); - ASSERT_NE(tmMd5, ""); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["trackMatte"] = tmMd5; + // from 0.52s-10s + TestPAGFile->setCurrentTime(800 * 1000); + ASSERT_EQ(TestPAGFile->currentTime(), 800 * 1000); + TestPAGPlayer->flush(); + auto tmMd5 = getMd5FromSnap(); + ASSERT_NE(tmMd5, ""); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["trackMatte"] = tmMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["trackMatte"]; - TraceIf(TestPAGSurface, "../test/out/trackMatte.png", cTrackMatte.get() != tmMd5); - EXPECT_EQ(cTrackMatte.get(), tmMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["trackMatte"]; + TraceIf(TestPAGSurface, "../test/out/trackMatte.png", cTrackMatte.get() != tmMd5); + EXPECT_EQ(cTrackMatte.get(), tmMd5); #endif } @@ -160,20 +160,20 @@ PAG_TEST_F(PAGLayerTest, trackMatte) { * 用例描述: PAGLayerTest测试visible接口 */ PAG_TEST_F(PAGLayerTest, visible) { - int target = 0; - TestPAGFile->setCurrentTime(5 * 1000000); - target = 0; - auto textLayer1 = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(textLayer1, nullptr); - textLayer1->setVisible(false); - TestPAGPlayer->flush(); - auto visibleMd5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["visible"] = visibleMd5; + int target = 0; + TestPAGFile->setCurrentTime(5 * 1000000); + target = 0; + auto textLayer1 = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(textLayer1, nullptr); + textLayer1->setVisible(false); + TestPAGPlayer->flush(); + auto visibleMd5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["visible"] = visibleMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["visible"]; - TraceIf(TestPAGSurface, "../test/out/pag_layer_visible.png", - cTrackMatte.get() != visibleMd5); - EXPECT_EQ(cTrackMatte.get(), visibleMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["visible"]; + TraceIf(TestPAGSurface, "../test/out/pag_layer_visible.png", + cTrackMatte.get() != visibleMd5); + EXPECT_EQ(cTrackMatte.get(), visibleMd5); #endif } @@ -181,27 +181,27 @@ PAG_TEST_F(PAGLayerTest, visible) { * 用例描述: PAGLayerTest测试matrix接口 */ PAG_TEST_F(PAGLayerTest, matrix) { - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto textLayer1 = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(textLayer1, nullptr); - textLayer1->setVisible(false); - target = 1; - auto textLayer2 = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(textLayer2, nullptr); - auto cM = Matrix(); - cM.setAll(1, 0, 728, 0, 1, 871, 0, 0, 1); - auto mtx = textLayer2->getTotalMatrix(); - ASSERT_TRUE(cM == mtx); - mtx.preScale(2, 2); - textLayer2->setMatrix(mtx); - TestPAGPlayer->flush(); - auto matrixMd5 = getMd5FromSnap(); - ASSERT_NE(matrixMd5, ""); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["matrix"] = matrixMd5; + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto textLayer1 = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(textLayer1, nullptr); + textLayer1->setVisible(false); + target = 1; + auto textLayer2 = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(textLayer2, nullptr); + auto cM = Matrix(); + cM.setAll(1, 0, 728, 0, 1, 871, 0, 0, 1); + auto mtx = textLayer2->getTotalMatrix(); + ASSERT_TRUE(cM == mtx); + mtx.preScale(2, 2); + textLayer2->setMatrix(mtx); + TestPAGPlayer->flush(); + auto matrixMd5 = getMd5FromSnap(); + ASSERT_NE(matrixMd5, ""); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["matrix"] = matrixMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["matrix"]; - EXPECT_EQ(cTrackMatte.get(), matrixMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["matrix"]; + EXPECT_EQ(cTrackMatte.get(), matrixMd5); #endif } @@ -209,15 +209,15 @@ PAG_TEST_F(PAGLayerTest, matrix) { * 用例描述: PAGLayerTest测试nextFrame接口 */ PAG_TEST_F(PAGLayerTest, nextFrame) { - TestPAGFile->setCurrentTime(1960000ll); - TestPAGFile->nextFrame(); - TestPAGPlayer->flush(); - auto nextFrameMd5 = getMd5FromSnap(); - ASSERT_NE(nextFrameMd5, ""); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["nextFrame"] = nextFrameMd5; + TestPAGFile->setCurrentTime(1960000ll); + TestPAGFile->nextFrame(); + TestPAGPlayer->flush(); + auto nextFrameMd5 = getMd5FromSnap(); + ASSERT_NE(nextFrameMd5, ""); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["nextFrame"] = nextFrameMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["nextFrame"]; - EXPECT_EQ(cTrackMatte.get(), nextFrameMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["nextFrame"]; + EXPECT_EQ(cTrackMatte.get(), nextFrameMd5); #endif } @@ -225,15 +225,15 @@ PAG_TEST_F(PAGLayerTest, nextFrame) { * 用例描述: PAGLayerTest测试preFrame接口 */ PAG_TEST_F(PAGLayerTest, preFrame) { - TestPAGFile->setCurrentTime(1960000ll); - TestPAGFile->nextFrame(); - TestPAGFile->preFrame(); - TestPAGPlayer->flush(); - auto preFrameMd5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["preFrame"] = preFrameMd5; + TestPAGFile->setCurrentTime(1960000ll); + TestPAGFile->nextFrame(); + TestPAGFile->preFrame(); + TestPAGPlayer->flush(); + auto preFrameMd5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["preFrame"] = preFrameMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["preFrame"]; - EXPECT_EQ(cTrackMatte.get(), preFrameMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["preFrame"]; + EXPECT_EQ(cTrackMatte.get(), preFrameMd5); #endif } @@ -243,15 +243,15 @@ PAG_TEST_CASE_WITH_PATH(PAGLayerFrameTest, "../assets/repeater.pag") * 用例描述: goToFrame测试 */ PAG_TEST_F(PAGLayerFrameTest, goToFrame) { - ASSERT_FALSE(TestPAGFile->gotoTime(0)); - ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(28, TestPAGFile->frameRateInternal()))); - ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(29, TestPAGFile->frameRateInternal()))); - ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(30, TestPAGFile->frameRateInternal()))); - ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(31, TestPAGFile->frameRateInternal()))); - ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(70, TestPAGFile->frameRateInternal()))); - //从区间内切换到区间外会有一次成功 - ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(600, TestPAGFile->frameRateInternal()))); - ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(601, TestPAGFile->frameRateInternal()))); + ASSERT_FALSE(TestPAGFile->gotoTime(0)); + ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(28, TestPAGFile->frameRateInternal()))); + ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(29, TestPAGFile->frameRateInternal()))); + ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(30, TestPAGFile->frameRateInternal()))); + ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(31, TestPAGFile->frameRateInternal()))); + ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(70, TestPAGFile->frameRateInternal()))); + //从区间内切换到区间外会有一次成功 + ASSERT_TRUE(TestPAGFile->gotoTime(FrameToTime(600, TestPAGFile->frameRateInternal()))); + ASSERT_FALSE(TestPAGFile->gotoTime(FrameToTime(601, TestPAGFile->frameRateInternal()))); } /** @@ -259,62 +259,62 @@ PAG_TEST_F(PAGLayerFrameTest, goToFrame) { */ // TODO(liamcli) 这里带后续外部滤镜注入接口优化完,需要修改本用例 PAG_TEST_F(PAGLayerTest, external_filter_ID79286937) { - // auto target = 1; - // std::shared_ptr imageLayer1 = std::static_pointer_cast( - // GetLayer(TestPAGFile, LayerType::Image, target)); - // Marker marker; - // marker.comment = "{\"filter\":[\"ShaderToy_BoDian\"]}"; - // - // auto filters = smart::SmartFilter::getShaderToyFilterParams({&marker}, - // imageLayer1->duration(), - // imageLayer1->frameRate()); - // auto pagFilter = PAGFilter::FromExternal(filters.front(), 500000); - // imageLayer1->addFilter(pagFilter); - // - // int targetIndex = 0; - // auto solidLayer = std::static_pointer_cast( - // GetLayer(TestPAGFile, LayerType::Solid, targetIndex)); - // solidLayer->setSolidColor(Black); - // - // TestPAGFile->setCurrentTime(2200000); - // TestPAGPlayer->flush(); - // auto md54 = DumpMD5(TestPAGSurface); - //// Trace(MakeSnapshot(TestPAGSurface), "../test/out/md54.png"); - // - // TestPAGFile->setCurrentTime(2600000); - // TestPAGPlayer->flush(); - // auto md55 = DumpMD5(TestPAGSurface); - //// Trace(MakeSnapshot(TestPAGSurface), "../test/out/md55.png"); - // - // PAGTestEnvironment::DumpJson["PAGLayerFilterTest"]["filter"]["md54"] = md54; - // PAGTestEnvironment::DumpJson["PAGLayerFilterTest"]["filter"]["md55"] = md55; - //#ifdef COMPARE_JSON_PATH - // auto cmd54 = PAGTestEnvironment::CompareJson["PAGLayerFilterTest"]["filter"]["md54"]; - // if (cmd54 != nullptr) { - // EXPECT_EQ(cmd54.get(), md54); - // } - // auto cmd55 = PAGTestEnvironment::CompareJson["PAGLayerFilterTest"]["filter"]["md55"]; - // if (cmd55 != nullptr) { - // EXPECT_EQ(cmd55.get(), md55); - // } - //#endif + // auto target = 1; + // std::shared_ptr imageLayer1 = std::static_pointer_cast( + // GetLayer(TestPAGFile, LayerType::Image, target)); + // Marker marker; + // marker.comment = "{\"filter\":[\"ShaderToy_BoDian\"]}"; + // + // auto filters = smart::SmartFilter::getShaderToyFilterParams({&marker}, + // imageLayer1->duration(), + // imageLayer1->frameRate()); + // auto pagFilter = PAGFilter::FromExternal(filters.front(), 500000); + // imageLayer1->addFilter(pagFilter); + // + // int targetIndex = 0; + // auto solidLayer = std::static_pointer_cast( + // GetLayer(TestPAGFile, LayerType::Solid, targetIndex)); + // solidLayer->setSolidColor(Black); + // + // TestPAGFile->setCurrentTime(2200000); + // TestPAGPlayer->flush(); + // auto md54 = DumpMD5(TestPAGSurface); + //// Trace(MakeSnapshot(TestPAGSurface), "../test/out/md54.png"); + // + // TestPAGFile->setCurrentTime(2600000); + // TestPAGPlayer->flush(); + // auto md55 = DumpMD5(TestPAGSurface); + //// Trace(MakeSnapshot(TestPAGSurface), "../test/out/md55.png"); + // + // PAGTestEnvironment::DumpJson["PAGLayerFilterTest"]["filter"]["md54"] = md54; + // PAGTestEnvironment::DumpJson["PAGLayerFilterTest"]["filter"]["md55"] = md55; + //#ifdef COMPARE_JSON_PATH + // auto cmd54 = PAGTestEnvironment::CompareJson["PAGLayerFilterTest"]["filter"]["md54"]; + // if (cmd54 != nullptr) { + // EXPECT_EQ(cmd54.get(), md54); + // } + // auto cmd55 = PAGTestEnvironment::CompareJson["PAGLayerFilterTest"]["filter"]["md55"]; + // if (cmd55 != nullptr) { + // EXPECT_EQ(cmd55.get(), md55); + // } + //#endif } /** * 用例描述: alpha 遮罩 */ PAG_TEST_F(PAGLayerTest, AlphaMask_ID80514761) { - auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.78); - TestPAGPlayer->flush(); - auto image = MakeSnapshot(TestPAGSurface); - auto preFrameMd5 = DumpMD5(image); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["alphaMask"] = preFrameMd5; + auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.78); + TestPAGPlayer->flush(); + auto image = MakeSnapshot(TestPAGSurface); + auto preFrameMd5 = DumpMD5(image); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["alphaMask"] = preFrameMd5; #ifdef COMPARE_JSON_PATH - auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["alphaMask"]; - TraceIf(image, "../test/out/alphaMask.png", cTrackMatte.get() != preFrameMd5); - EXPECT_EQ(cTrackMatte.get(), preFrameMd5); + auto cTrackMatte = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["alphaMask"]; + TraceIf(image, "../test/out/alphaMask.png", cTrackMatte.get() != preFrameMd5); + EXPECT_EQ(cTrackMatte.get(), preFrameMd5); #endif } @@ -322,33 +322,33 @@ PAG_TEST_F(PAGLayerTest, AlphaMask_ID80514761) { * 用例描述: 文字缩放 */ PAG_TEST_F(PAGLayerTest, TextScale_81527319) { - auto pagFile = PAGFile::Load("../resources/apitest/TEXT04.pag"); - auto textData = pagFile->getTextData(0); - textData->text = "耶"; - pagFile->replaceText(0, textData); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(500, 500); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - auto centerX = static_cast(pagSurface->width()) * 0.5f; - auto centerY = static_cast(pagSurface->height()) * 0.5f; - auto fileCenterX = static_cast(pagFile->width()) * 0.5f; - auto fileCenterY = static_cast(pagFile->height()) * 0.5f; - auto matrix = Matrix::I(); - matrix.postTranslate(centerX - fileCenterX, centerY - fileCenterY); - matrix.postScale(10.187f, 10.187f, centerX, centerY); - pagPlayer->setMatrix(matrix); - pagPlayer->setProgress(0.5f); - pagPlayer->flush(); - auto skImage = MakeSnapshot(pagSurface); - auto dumpMd5 = DumpMD5(skImage); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["textScale"] = dumpMd5; + auto pagFile = PAGFile::Load("../resources/apitest/TEXT04.pag"); + auto textData = pagFile->getTextData(0); + textData->text = "耶"; + pagFile->replaceText(0, textData); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(500, 500); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + auto centerX = static_cast(pagSurface->width()) * 0.5f; + auto centerY = static_cast(pagSurface->height()) * 0.5f; + auto fileCenterX = static_cast(pagFile->width()) * 0.5f; + auto fileCenterY = static_cast(pagFile->height()) * 0.5f; + auto matrix = Matrix::I(); + matrix.postTranslate(centerX - fileCenterX, centerY - fileCenterY); + matrix.postScale(10.187f, 10.187f, centerX, centerY); + pagPlayer->setMatrix(matrix); + pagPlayer->setProgress(0.5f); + pagPlayer->flush(); + auto skImage = MakeSnapshot(pagSurface); + auto dumpMd5 = DumpMD5(skImage); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["textScale"] = dumpMd5; #ifdef COMPARE_JSON_PATH - auto textScaleMD5 = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["textScale"]; - TraceIf(skImage, "../test/out/textScale.png", textScaleMD5.get() != dumpMd5); - EXPECT_EQ(textScaleMD5.get(), dumpMd5); + auto textScaleMD5 = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["textScale"]; + TraceIf(skImage, "../test/out/textScale.png", textScaleMD5.get() != dumpMd5); + EXPECT_EQ(textScaleMD5.get(), dumpMd5); #endif } @@ -356,24 +356,24 @@ PAG_TEST_F(PAGLayerTest, TextScale_81527319) { * 用例描述: 透明度设置 */ PAG_TEST_F(PAGLayerTest, Opacity) { - auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); - ASSERT_NE(pagFile, nullptr); - pagFile->setOpacity(128); - ASSERT_EQ(pagFile->opacity(), 128); - auto pagSurface = PAGSurface::MakeOffscreen(500, 500); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setProgress(0.5f); - pagPlayer->flush(); - auto skImage = MakeSnapshot(pagSurface); - auto dumpMd5 = DumpMD5(skImage); - PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["opacity"] = dumpMd5; + auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); + ASSERT_NE(pagFile, nullptr); + pagFile->setOpacity(128); + ASSERT_EQ(pagFile->opacity(), 128); + auto pagSurface = PAGSurface::MakeOffscreen(500, 500); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setProgress(0.5f); + pagPlayer->flush(); + auto skImage = MakeSnapshot(pagSurface); + auto dumpMd5 = DumpMD5(skImage); + PAGTestEnvironment::DumpJson["PAGLayerTest"]["layer"]["opacity"] = dumpMd5; #ifdef COMPARE_JSON_PATH - auto opacityMD5 = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["opacity"]; - TraceIf(skImage, "../test/out/opacity.png", opacityMD5.get() != dumpMd5); - EXPECT_EQ(opacityMD5.get(), dumpMd5); + auto opacityMD5 = PAGTestEnvironment::CompareJson["PAGLayerTest"]["layer"]["opacity"]; + TraceIf(skImage, "../test/out/opacity.png", opacityMD5.get() != dumpMd5); + EXPECT_EQ(opacityMD5.get(), dumpMd5); #endif } } // namespace pag diff --git a/test/PAGMD5Test.cpp b/test/PAGMD5Test.cpp index f798777f3b..36fb3fcfa6 100644 --- a/test/PAGMD5Test.cpp +++ b/test/PAGMD5Test.cpp @@ -38,167 +38,167 @@ using nlohmann::json; static constexpr bool PrintPerformance = false; struct RenderCost { - int64_t totalTime = 0; - int64_t readPixelsCost = 0; - int64_t md5Cost = 0; - std::string performance; + int64_t totalTime = 0; + int64_t readPixelsCost = 0; + int64_t md5Cost = 0; + std::string performance; }; class MD5Task : public Executor { - public: - MD5Task(Frame currentFrame, Bitmap bitmap) - : _currentFrame(currentFrame), _bitmap(std::move(bitmap)) { - } - - Frame currentFrame() const { - return _currentFrame; - } - - Bitmap bitmap() const { - return _bitmap; - } - - std::string md5() { - return _md5; - } - - private: - Frame _currentFrame = 0; - Bitmap _bitmap = {}; - std::string _md5; - - void execute() override { - _md5 = DumpMD5(_bitmap); - } -}; - -void DumpFileMD5(Semaphore* semaphore, std::string pagPath, json* compareJson, json* dumpJson) { - auto timer = GetTimer(); - auto fileName = pagPath.substr(pagPath.rfind('/') + 1, pagPath.size()); - std::vector compare = {}; - std::vector output = {}; - if (compareJson->contains(fileName) && (*compareJson)[fileName].is_array()) { - compare = (*compareJson)[fileName].get>(); - } - auto pagFile = PAGFile::Load(pagPath); - ASSERT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - - Frame totalFrames = TimeToFrame(pagFile->duration(), pagFile->frameRate()); - Frame currentFrame = 0; - std::string errorMsg; - std::map performanceMap = {}; - - bool status = true; - Bitmap currentBitmap = {}; - std::shared_ptr lastMD5 = nullptr; - - auto CompareMD5 = [&](Frame currentFrame) { - auto startTime = GetTimer(); - auto md5Task = static_cast(lastMD5->wait()); - auto md5 = md5Task->md5(); - auto md5Cost = GetTimer() - startTime; - if (currentFrame == md5Task->currentFrame()) { - auto& cost = performanceMap[currentFrame]; - cost.md5Cost = md5Cost; - cost.totalTime += md5Cost; +public: + MD5Task(Frame currentFrame, Bitmap bitmap) + : _currentFrame(currentFrame), _bitmap(std::move(bitmap)) { } - output.push_back(md5); - if (!compare.empty() && compare[currentFrame] != md5) { - errorMsg += (std::to_string(currentFrame) + ";"); - if (status) { - auto imagePath = "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; - Trace(md5Task->bitmap(), imagePath); - status = false; - } + + Frame currentFrame() const { + return _currentFrame; } - }; - - while (currentFrame < totalFrames) { - auto changed = pagPlayer->flush(); - if (changed) { - RenderCost cost = {}; - auto starTime = GetTimer(); - currentBitmap = MakeSnapshot(pagSurface); - cost.readPixelsCost = GetTimer() - starTime; - auto cache = pagPlayer->renderCache; - cost.totalTime = cache->totalTime + cost.readPixelsCost; - cost.performance = cache->getPerformanceString(); - performanceMap[currentFrame] = cost; + + Bitmap bitmap() const { + return _bitmap; } - if (currentFrame > 0) { - CompareMD5(currentFrame - 1); + + std::string md5() { + return _md5; } - if (changed) { - auto executor = new MD5Task(currentFrame, currentBitmap); - lastMD5 = Task::Make(std::unique_ptr(executor)); - lastMD5->run(); + +private: + Frame _currentFrame = 0; + Bitmap _bitmap = {}; + std::string _md5; + + void execute() override { + _md5 = DumpMD5(_bitmap); } - pagPlayer->nextFrame(); - currentFrame++; - } - CompareMD5(currentFrame - 1); +}; - auto cost = static_cast(GetTimer() - timer) / 1000000; - if (PrintPerformance) { - LOGI( - "========================================== %s : start" - " ==========================================", - fileName.c_str()); - for (auto& item : performanceMap) { - // if (item.second.totalTime < 10000) { // 小于10ms不打印 - // continue; - // } - auto& renderCost = item.second; - LOGI("%4d | %6.1fms :%s %6.1fms[Pixels] %6.1fms[MD5]", item.first, - renderCost.totalTime / 1000.0, renderCost.performance.c_str(), - renderCost.readPixelsCost / 1000.0, renderCost.md5Cost / 1000.0); +void DumpFileMD5(Semaphore* semaphore, std::string pagPath, json* compareJson, json* dumpJson) { + auto timer = GetTimer(); + auto fileName = pagPath.substr(pagPath.rfind('/') + 1, pagPath.size()); + std::vector compare = {}; + std::vector output = {}; + if (compareJson->contains(fileName) && (*compareJson)[fileName].is_array()) { + compare = (*compareJson)[fileName].get>(); + } + auto pagFile = PAGFile::Load(pagPath); + ASSERT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + + Frame totalFrames = TimeToFrame(pagFile->duration(), pagFile->frameRate()); + Frame currentFrame = 0; + std::string errorMsg; + std::map performanceMap = {}; + + bool status = true; + Bitmap currentBitmap = {}; + std::shared_ptr lastMD5 = nullptr; + + auto CompareMD5 = [&](Frame currentFrame) { + auto startTime = GetTimer(); + auto md5Task = static_cast(lastMD5->wait()); + auto md5 = md5Task->md5(); + auto md5Cost = GetTimer() - startTime; + if (currentFrame == md5Task->currentFrame()) { + auto& cost = performanceMap[currentFrame]; + cost.md5Cost = md5Cost; + cost.totalTime += md5Cost; + } + output.push_back(md5); + if (!compare.empty() && compare[currentFrame] != md5) { + errorMsg += (std::to_string(currentFrame) + ";"); + if (status) { + auto imagePath = "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; + Trace(md5Task->bitmap(), imagePath); + status = false; + } + } + }; + + while (currentFrame < totalFrames) { + auto changed = pagPlayer->flush(); + if (changed) { + RenderCost cost = {}; + auto starTime = GetTimer(); + currentBitmap = MakeSnapshot(pagSurface); + cost.readPixelsCost = GetTimer() - starTime; + auto cache = pagPlayer->renderCache; + cost.totalTime = cache->totalTime + cost.readPixelsCost; + cost.performance = cache->getPerformanceString(); + performanceMap[currentFrame] = cost; + } + if (currentFrame > 0) { + CompareMD5(currentFrame - 1); + } + if (changed) { + auto executor = new MD5Task(currentFrame, currentBitmap); + lastMD5 = Task::Make(std::unique_ptr(executor)); + lastMD5->run(); + } + pagPlayer->nextFrame(); + currentFrame++; } - } - EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; - LOGI( - "====================================== %s : %.2fs " - "======================================\n", - fileName.c_str(), cost); - (*dumpJson)[fileName] = output; - semaphore->signal(); + CompareMD5(currentFrame - 1); + + auto cost = static_cast(GetTimer() - timer) / 1000000; + if (PrintPerformance) { + LOGI( + "========================================== %s : start" + " ==========================================", + fileName.c_str()); + for (auto& item : performanceMap) { + // if (item.second.totalTime < 10000) { // 小于10ms不打印 + // continue; + // } + auto& renderCost = item.second; + LOGI("%4d | %6.1fms :%s %6.1fms[Pixels] %6.1fms[MD5]", item.first, + renderCost.totalTime / 1000.0, renderCost.performance.c_str(), + renderCost.readPixelsCost / 1000.0, renderCost.md5Cost / 1000.0); + } + } + EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; + LOGI( + "====================================== %s : %.2fs " + "======================================\n", + fileName.c_str(), cost); + (*dumpJson)[fileName] = output; + semaphore->signal(); } /** * 用例描述: 校验md5文件夹中各个文件渲染结果 */ PAG_TEST(SimplePAGMD5Test, TestMD5) { - json dumpJson; - json compareJson; - std::ifstream inputFile("../test/res/compare_md5_dump.json"); - if (inputFile) { - inputFile >> compareJson; - } - std::vector files; - GetAllPAGFiles("../resources/md5", files); - - // 强制仅测试指定文件的MD5 - // files.clear(); - // files.push_back("../resources/md5/vt_zhongyudd.pag"); - - static const int MAX_THREADS = 6; - Semaphore semaphore(MAX_THREADS); - std::vector threads = {}; - for (auto& file : files) { - semaphore.wait(); - threads.emplace_back(DumpFileMD5, &semaphore, file, &compareJson, &dumpJson); - } - for (auto& thread : threads) { - thread.join(); - } - - std::ofstream outFile("../test/out/compare_md5_dump.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + json dumpJson; + json compareJson; + std::ifstream inputFile("../test/res/compare_md5_dump.json"); + if (inputFile) { + inputFile >> compareJson; + } + std::vector files; + GetAllPAGFiles("../resources/md5", files); + + // 强制仅测试指定文件的MD5 + // files.clear(); + // files.push_back("../resources/md5/vt_zhongyudd.pag"); + + static const int MAX_THREADS = 6; + Semaphore semaphore(MAX_THREADS); + std::vector threads = {}; + for (auto& file : files) { + semaphore.wait(); + threads.emplace_back(DumpFileMD5, &semaphore, file, &compareJson, &dumpJson); + } + for (auto& thread : threads) { + thread.join(); + } + + std::ofstream outFile("../test/out/compare_md5_dump.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } } // namespace pag #endif diff --git a/test/PAGPerformanceTest.cpp b/test/PAGPerformanceTest.cpp index 9febe99d57..093a323233 100644 --- a/test/PAGPerformanceTest.cpp +++ b/test/PAGPerformanceTest.cpp @@ -31,125 +31,125 @@ namespace pag { using nlohmann::json; double NumberGap(int64_t num1, int64_t num2) { - return (num2 - num1) * 1.0 / num1; + return (num2 - num1) * 1.0 / num1; } bool Accept(double result) { - return result <= 0.05; + return result <= 0.05; } /** * 用例描述: 测试渲染性能 */ PAG_TEST(PerformanceTest, TestRender) { - json renderJson; - json graphicsJson; - - json compareRenderJson; - std::ifstream inputRenderFile("../test/res/compare_performance_render.json"); - bool needCompareRender = false; - if (inputRenderFile) { - needCompareRender = true; - inputRenderFile >> compareRenderJson; - } - - json compareGraphicsJson; - std::ifstream inputGraphicsFile("../test/res/compare_performance_graphics.json"); - bool needCompareGraphics = false; - if (inputGraphicsFile) { - needCompareGraphics = true; - inputGraphicsFile >> compareGraphicsJson; - } - - std::vector files; - GetAllPAGFiles("../resources/smoke", files); - - for (size_t i = 0; i < files.size(); i++) { - auto fileName = files[i].substr(files[i].rfind('/') + 1, files[i].size()); - std::vector compareRenderVector; - std::vector compareGraphicsVector; - - bool needCompareRenderThis = false; - bool needCompareGraphicsThis = false; - if (needCompareRender && compareRenderJson.contains(fileName) && - compareRenderJson[fileName].is_array()) { - compareRenderVector = compareRenderJson[fileName].get>(); - needCompareRenderThis = true; - } - if (needCompareGraphics && compareGraphicsJson.contains(fileName) && - compareGraphicsJson[fileName].is_array()) { - compareGraphicsVector = compareGraphicsJson[fileName].get>(); - needCompareGraphicsThis = true; + json renderJson; + json graphicsJson; + + json compareRenderJson; + std::ifstream inputRenderFile("../test/res/compare_performance_render.json"); + bool needCompareRender = false; + if (inputRenderFile) { + needCompareRender = true; + inputRenderFile >> compareRenderJson; } - auto TestPAGFile = PAGFile::Load(files[i]); - ASSERT_NE(TestPAGFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(TestPAGFile); - - Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); - Frame currentFrame = 0; - - std::vector renderVector; - std::vector graphicsVector; - std::string errorMsg; - - int64_t totalTime = 0; - int64_t totalGraphics = 0; - - while (currentFrame < totalFrames) { - pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); - int64_t frameTime = GetTimer(); - pagPlayer->flush(); - frameTime = GetTimer() - frameTime; - - int64_t graphicsMemory = pagPlayer->graphicsMemory(); - if (currentFrame > 0) { - // 先不统计第0帧 - totalTime += frameTime; - totalGraphics += graphicsMemory; - } - - currentFrame++; - } - std::cout << "\n frameTime: " << totalTime / (totalFrames - 1) - << " graphicsMemory: " << totalGraphics / (totalFrames - 1) << std::endl; - - int64_t avgTotalTime = totalTime / (totalFrames - 1); - renderVector.push_back(std::to_string(avgTotalTime)); - int64_t avgTotalGraphics = totalGraphics / (totalFrames - 1); - graphicsVector.push_back(std::to_string(avgTotalGraphics)); - - double renderResult = NumberGap(std::stoll(compareRenderVector[i]), avgTotalTime); - if (needCompareRenderThis && !Accept(renderResult)) { - errorMsg += "frame" + std::to_string(currentFrame) + - " render out of time:" + std::to_string(renderResult); - std::string imagePath = - "../test/out/" + fileName + "_render_" + std::to_string(currentFrame) + ".png"; - Trace(MakeSnapshot(pagSurface), imagePath); + json compareGraphicsJson; + std::ifstream inputGraphicsFile("../test/res/compare_performance_graphics.json"); + bool needCompareGraphics = false; + if (inputGraphicsFile) { + needCompareGraphics = true; + inputGraphicsFile >> compareGraphicsJson; } - double graphicsResult = NumberGap(std::stoll(compareGraphicsVector[i]), avgTotalGraphics); - if (needCompareGraphicsThis && !Accept(graphicsResult)) { - errorMsg += "frame" + std::to_string(currentFrame) + - " graphics to much:" + std::to_string(graphicsResult); - std::string imagePath = - "../test/out/" + fileName + "_graphics_" + std::to_string(currentFrame) + ".png"; - Trace(MakeSnapshot(pagSurface), imagePath); + + std::vector files; + GetAllPAGFiles("../resources/smoke", files); + + for (size_t i = 0; i < files.size(); i++) { + auto fileName = files[i].substr(files[i].rfind('/') + 1, files[i].size()); + std::vector compareRenderVector; + std::vector compareGraphicsVector; + + bool needCompareRenderThis = false; + bool needCompareGraphicsThis = false; + if (needCompareRender && compareRenderJson.contains(fileName) && + compareRenderJson[fileName].is_array()) { + compareRenderVector = compareRenderJson[fileName].get>(); + needCompareRenderThis = true; + } + if (needCompareGraphics && compareGraphicsJson.contains(fileName) && + compareGraphicsJson[fileName].is_array()) { + compareGraphicsVector = compareGraphicsJson[fileName].get>(); + needCompareGraphicsThis = true; + } + + auto TestPAGFile = PAGFile::Load(files[i]); + ASSERT_NE(TestPAGFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(TestPAGFile); + + Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); + Frame currentFrame = 0; + + std::vector renderVector; + std::vector graphicsVector; + std::string errorMsg; + + int64_t totalTime = 0; + int64_t totalGraphics = 0; + + while (currentFrame < totalFrames) { + pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); + int64_t frameTime = GetTimer(); + pagPlayer->flush(); + frameTime = GetTimer() - frameTime; + + int64_t graphicsMemory = pagPlayer->graphicsMemory(); + if (currentFrame > 0) { + // 先不统计第0帧 + totalTime += frameTime; + totalGraphics += graphicsMemory; + } + + currentFrame++; + } + std::cout << "\n frameTime: " << totalTime / (totalFrames - 1) + << " graphicsMemory: " << totalGraphics / (totalFrames - 1) << std::endl; + + int64_t avgTotalTime = totalTime / (totalFrames - 1); + renderVector.push_back(std::to_string(avgTotalTime)); + int64_t avgTotalGraphics = totalGraphics / (totalFrames - 1); + graphicsVector.push_back(std::to_string(avgTotalGraphics)); + + double renderResult = NumberGap(std::stoll(compareRenderVector[i]), avgTotalTime); + if (needCompareRenderThis && !Accept(renderResult)) { + errorMsg += "frame" + std::to_string(currentFrame) + + " render out of time:" + std::to_string(renderResult); + std::string imagePath = + "../test/out/" + fileName + "_render_" + std::to_string(currentFrame) + ".png"; + Trace(MakeSnapshot(pagSurface), imagePath); + } + double graphicsResult = NumberGap(std::stoll(compareGraphicsVector[i]), avgTotalGraphics); + if (needCompareGraphicsThis && !Accept(graphicsResult)) { + errorMsg += "frame" + std::to_string(currentFrame) + + " graphics to much:" + std::to_string(graphicsResult); + std::string imagePath = + "../test/out/" + fileName + "_graphics_" + std::to_string(currentFrame) + ".png"; + Trace(MakeSnapshot(pagSurface), imagePath); + } + EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; + renderJson[fileName] = renderVector; + graphicsJson[fileName] = graphicsVector; } - EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; - renderJson[fileName] = renderVector; - graphicsJson[fileName] = graphicsVector; - } - std::ofstream outRenderFile("../test/out/performance_render.json"); - outRenderFile << std::setw(4) << renderJson << std::endl; - outRenderFile.close(); - - std::ofstream outGraphicsFile("../test/out/performance_graphics.json"); - outGraphicsFile << std::setw(4) << graphicsJson << std::endl; - outGraphicsFile.close(); + std::ofstream outRenderFile("../test/out/performance_render.json"); + outRenderFile << std::setw(4) << renderJson << std::endl; + outRenderFile.close(); + + std::ofstream outGraphicsFile("../test/out/performance_graphics.json"); + outGraphicsFile << std::setw(4) << graphicsJson << std::endl; + outGraphicsFile.close(); } } // namespace pag #endif \ No newline at end of file diff --git a/test/PAGPlayerTest.cpp b/test/PAGPlayerTest.cpp index 3126c79b37..8812c8e191 100644 --- a/test/PAGPlayerTest.cpp +++ b/test/PAGPlayerTest.cpp @@ -29,55 +29,57 @@ PAG_TEST_CASE(PAGPlayerTest) * 用例描述: PAGPlayer setComposition基础功能 */ PAG_TEST_F(PAGPlayerTest, setComposition) { - TestPAGPlayer->setComposition(nullptr); - ASSERT_EQ(TestPAGPlayer->getComposition(), nullptr); - auto container = PAGComposition::Make(720, 1080); - TestPAGPlayer->setComposition(container); - ASSERT_NE(TestPAGPlayer->getComposition(), nullptr); + TestPAGPlayer->setComposition(nullptr); + ASSERT_EQ(TestPAGPlayer->getComposition(), nullptr); + auto container = PAGComposition::Make(720, 1080); + TestPAGPlayer->setComposition(container); + ASSERT_NE(TestPAGPlayer->getComposition(), nullptr); } /** * 用例描述: PAGPlayerTest基础功能 */ PAG_TEST_F(PAGPlayerTest, pagPlayer) { - auto container = PAGComposition::Make(720, 1080); - TestPAGPlayer->setComposition(container); - ASSERT_NE(TestPAGPlayer->getComposition(), nullptr); - auto rootLayer = PAGFile::Load(DEFAULT_PAG_PATH); - auto pagCom = std::static_pointer_cast(rootLayer->getLayerAt(0)); - int size = pagCom->numChildren(); - for (int i = 0; i < size; i++) { - auto layer = pagCom->getLayerAt(0); - layer->setCurrentTime(3 * 1000000); - container->addLayer(pagCom->getLayerAt(0)); - } - - ASSERT_EQ(TestPAGSurface->width(), 720); - ASSERT_EQ(TestPAGSurface->height(), 1080); - ASSERT_EQ(container->numChildren(), 6); - - auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); - auto pagComposition2 = std::static_pointer_cast(pagFile2->getLayerAt(0)); - TestPAGPlayer->setComposition(pagComposition2); - TestPAGPlayer->flush(); - auto setCompositionMd5 = getMd5FromSnap(); - - TestPAGPlayer->setComposition(container); - TestPAGPlayer->flush(); - auto setComposition2Md5 = getMd5FromSnap(); - - json out = { - {"pagPlayer", - {{"setCompositionMd5", setCompositionMd5}, {"setComposition2Md5", setComposition2Md5}}}}; - PAGTestEnvironment::DumpJson["PAGPlayerTest"] = out; + auto container = PAGComposition::Make(720, 1080); + TestPAGPlayer->setComposition(container); + ASSERT_NE(TestPAGPlayer->getComposition(), nullptr); + auto rootLayer = PAGFile::Load(DEFAULT_PAG_PATH); + auto pagCom = std::static_pointer_cast(rootLayer->getLayerAt(0)); + int size = pagCom->numChildren(); + for (int i = 0; i < size; i++) { + auto layer = pagCom->getLayerAt(0); + layer->setCurrentTime(3 * 1000000); + container->addLayer(pagCom->getLayerAt(0)); + } + + ASSERT_EQ(TestPAGSurface->width(), 720); + ASSERT_EQ(TestPAGSurface->height(), 1080); + ASSERT_EQ(container->numChildren(), 6); + + auto pagFile2 = PAGFile::Load(DEFAULT_PAG_PATH); + auto pagComposition2 = std::static_pointer_cast(pagFile2->getLayerAt(0)); + TestPAGPlayer->setComposition(pagComposition2); + TestPAGPlayer->flush(); + auto setCompositionMd5 = getMd5FromSnap(); + + TestPAGPlayer->setComposition(container); + TestPAGPlayer->flush(); + auto setComposition2Md5 = getMd5FromSnap(); + + json out = { + { "pagPlayer", + {{"setCompositionMd5", setCompositionMd5}, {"setComposition2Md5", setComposition2Md5}} + } + }; + PAGTestEnvironment::DumpJson["PAGPlayerTest"] = out; #ifdef COMPARE_JSON_PATH - auto cSetCompositionMd5 = - PAGTestEnvironment::CompareJson["PAGPlayerTest"]["pagPlayer"]["setCompositionMd5"]; - EXPECT_EQ(cSetCompositionMd5.get(), setCompositionMd5); - auto cSetComposition2Md5 = - PAGTestEnvironment::CompareJson["PAGPlayerTest"]["pagPlayer"]["setComposition2Md5"]; - EXPECT_EQ(cSetComposition2Md5.get(), setComposition2Md5); + auto cSetCompositionMd5 = + PAGTestEnvironment::CompareJson["PAGPlayerTest"]["pagPlayer"]["setCompositionMd5"]; + EXPECT_EQ(cSetCompositionMd5.get(), setCompositionMd5); + auto cSetComposition2Md5 = + PAGTestEnvironment::CompareJson["PAGPlayerTest"]["pagPlayer"]["setComposition2Md5"]; + EXPECT_EQ(cSetComposition2Md5.get(), setComposition2Md5); #endif } @@ -85,95 +87,95 @@ PAG_TEST_F(PAGPlayerTest, pagPlayer) { * 用例描述: PAGPlayerTest 切换PAGSurface */ PAG_TEST_F(PAGPlayerTest, switchPAGSurface) { - auto pagFile1 = PAGFile::Load("../resources/apitest/test.pag"); - auto pagSurface1 = PAGSurface::MakeOffscreen(pagFile1->width(), pagFile1->height()); - auto pagPlayer1 = new PAGPlayer(); - pagPlayer1->setSurface(pagSurface1); - pagPlayer1->setComposition(pagFile1); - pagPlayer1->setProgress(0); - pagPlayer1->flush(); - pagPlayer1->setSurface(nullptr); - - auto pagPlayer2 = new PAGPlayer(); - auto pagFile2 = PAGFile::Load("../resources/apitest/ZC2.pag"); - pagPlayer2->setComposition(pagFile2); - pagPlayer2->setSurface(pagSurface1); - pagPlayer2->setProgress(0.5f); - auto status = pagPlayer2->flush(); - ASSERT_EQ(status, true); - - auto skImage = MakeSnapshot(pagSurface1); - std::string md5 = DumpMD5(skImage); + auto pagFile1 = PAGFile::Load("../resources/apitest/test.pag"); + auto pagSurface1 = PAGSurface::MakeOffscreen(pagFile1->width(), pagFile1->height()); + auto pagPlayer1 = new PAGPlayer(); + pagPlayer1->setSurface(pagSurface1); + pagPlayer1->setComposition(pagFile1); + pagPlayer1->setProgress(0); + pagPlayer1->flush(); + pagPlayer1->setSurface(nullptr); + + auto pagPlayer2 = new PAGPlayer(); + auto pagFile2 = PAGFile::Load("../resources/apitest/ZC2.pag"); + pagPlayer2->setComposition(pagFile2); + pagPlayer2->setSurface(pagSurface1); + pagPlayer2->setProgress(0.5f); + auto status = pagPlayer2->flush(); + ASSERT_EQ(status, true); + + auto skImage = MakeSnapshot(pagSurface1); + std::string md5 = DumpMD5(skImage); #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceSwitchTest"]["switchPAGSurface"]; - std::string imagePath = "../test/out/switchPAGSurface.png"; - TraceIf(skImage, imagePath, md5 != compareMD5); - PAGTestEnvironment::DumpJson["PAGSurfaceSwitchTest"]["switchPAGSurface"] = md5; - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceSwitchTest"]["switchPAGSurface"]; + std::string imagePath = "../test/out/switchPAGSurface.png"; + TraceIf(skImage, imagePath, md5 != compareMD5); + PAGTestEnvironment::DumpJson["PAGSurfaceSwitchTest"]["switchPAGSurface"] = md5; + EXPECT_EQ(compareMD5.get(), md5); #endif - delete pagPlayer1; - delete pagPlayer2; + delete pagPlayer1; + delete pagPlayer2; } /** * 用例描述: PAGPlayerTest基础功能 */ PAG_TEST_F(PAGPlayerTest, autoClear) { - auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - auto pagPlayer = new PAGPlayer(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->flush(); - - auto pagFile2 = PAGFile::Load("../resources/gradient/grad_alpha.pag"); - pagPlayer->setComposition(pagFile2); - pagPlayer->setAutoClear(false); - pagPlayer->flush(); - - json outputJson = {}; - json compareJson = PAGTestEnvironment::CompareJson["PAGPlayerAutoClearTest"]; - - Bitmap bitmap = {}; - auto result = bitmap.allocPixels(pagSurface->width(), pagSurface->height()); - ASSERT_TRUE(result); - BitmapLock lock(bitmap); - PixelMap pixelMap(bitmap.info(), lock.pixels()); - result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), - pixelMap.rowBytes()); - ASSERT_TRUE(result); - auto md5 = DumpMD5(pixelMap); - std::string key = "autoClear_false_flush0"; - outputJson[key] = md5; - TraceIf(pixelMap, "../test/out/" + std::string(key) + ".png", compareJson[key] != md5); - EXPECT_EQ(compareJson["autoClear_false_flush0"].get(), md5); - - pagPlayer->flush(); - result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), - pixelMap.rowBytes()); - ASSERT_TRUE(result); - md5 = DumpMD5(pixelMap); - key = "autoClear_false_flush1"; - outputJson[key] = md5; - if (compareJson != nullptr && compareJson[key] != nullptr) { + auto pagFile = PAGFile::Load("../resources/apitest/AlphaTrackMatte.pag"); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + auto pagPlayer = new PAGPlayer(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->flush(); + + auto pagFile2 = PAGFile::Load("../resources/gradient/grad_alpha.pag"); + pagPlayer->setComposition(pagFile2); + pagPlayer->setAutoClear(false); + pagPlayer->flush(); + + json outputJson = {}; + json compareJson = PAGTestEnvironment::CompareJson["PAGPlayerAutoClearTest"]; + + Bitmap bitmap = {}; + auto result = bitmap.allocPixels(pagSurface->width(), pagSurface->height()); + ASSERT_TRUE(result); + BitmapLock lock(bitmap); + PixelMap pixelMap(bitmap.info(), lock.pixels()); + result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), + pixelMap.rowBytes()); + ASSERT_TRUE(result); + auto md5 = DumpMD5(pixelMap); + std::string key = "autoClear_false_flush0"; + outputJson[key] = md5; TraceIf(pixelMap, "../test/out/" + std::string(key) + ".png", compareJson[key] != md5); - EXPECT_EQ(compareJson["autoClear_false_flush1"].get(), md5); - } - - pagPlayer->setAutoClear(true); - pagPlayer->flush(); - result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), - pixelMap.rowBytes()); - ASSERT_TRUE(result); - md5 = DumpMD5(pixelMap); - key = "autoClear_true"; - outputJson[key] = md5; - if (compareJson != nullptr && compareJson[key] != nullptr) { - TraceIf(pixelMap, "../test/out/" + std::string(key) + ".png", compareJson[key] != md5); - EXPECT_EQ(compareJson["autoClear_true"].get(), md5); - } - - PAGTestEnvironment::DumpJson["PAGPlayerAutoClearTest"] = outputJson; + EXPECT_EQ(compareJson["autoClear_false_flush0"].get(), md5); + + pagPlayer->flush(); + result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), + pixelMap.rowBytes()); + ASSERT_TRUE(result); + md5 = DumpMD5(pixelMap); + key = "autoClear_false_flush1"; + outputJson[key] = md5; + if (compareJson != nullptr && compareJson[key] != nullptr) { + TraceIf(pixelMap, "../test/out/" + std::string(key) + ".png", compareJson[key] != md5); + EXPECT_EQ(compareJson["autoClear_false_flush1"].get(), md5); + } + + pagPlayer->setAutoClear(true); + pagPlayer->flush(); + result = pagSurface->readPixels(pixelMap.colorType(), pixelMap.alphaType(), lock.pixels(), + pixelMap.rowBytes()); + ASSERT_TRUE(result); + md5 = DumpMD5(pixelMap); + key = "autoClear_true"; + outputJson[key] = md5; + if (compareJson != nullptr && compareJson[key] != nullptr) { + TraceIf(pixelMap, "../test/out/" + std::string(key) + ".png", compareJson[key] != md5); + EXPECT_EQ(compareJson["autoClear_true"].get(), md5); + } + + PAGTestEnvironment::DumpJson["PAGPlayerAutoClearTest"] = outputJson; } } // namespace pag \ No newline at end of file diff --git a/test/PAGRasterizerTest.cpp b/test/PAGRasterizerTest.cpp index c649bd78e4..695b626c8c 100644 --- a/test/PAGRasterizerTest.cpp +++ b/test/PAGRasterizerTest.cpp @@ -33,72 +33,72 @@ using nlohmann::json; * 用例描述: 矢量栅格化相关功能测试 */ PAG_TEST(PAGRasterizerTest, TestRasterizer) { - Path path = {}; - path.addRect(100, 100, 400, 400); - path.addRoundRect(Rect::MakeLTRB(150, 150, 350, 350), 30, 20, true); - path.addOval(Rect::MakeLTRB(200, 200, 300, 300)); - // 501*501 是为了测试 GL_UNPACK_ALIGNMENT - auto mask = Mask::Make(501, 501); - ASSERT_TRUE(mask != nullptr); - auto matrix = Matrix::MakeTrans(50, 50); - mask->setMatrix(matrix); - mask->fillPath(path); - auto pixelBuffer = std::static_pointer_cast(mask)->getBuffer(); - std::string pathMD5 = DumpMD5(pixelBuffer); - json rasterizerJson = {{"rasterizer_path", pathMD5}}; - auto pathCompareMD5 = PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_path"]; - std::string imagePath = "../test/out/rasterizer_path.png"; - TraceIf(pixelBuffer, imagePath, pathMD5 != pathCompareMD5); - EXPECT_EQ(pathCompareMD5.get(), pathMD5); + Path path = {}; + path.addRect(100, 100, 400, 400); + path.addRoundRect(Rect::MakeLTRB(150, 150, 350, 350), 30, 20, true); + path.addOval(Rect::MakeLTRB(200, 200, 300, 300)); + // 501*501 是为了测试 GL_UNPACK_ALIGNMENT + auto mask = Mask::Make(501, 501); + ASSERT_TRUE(mask != nullptr); + auto matrix = Matrix::MakeTrans(50, 50); + mask->setMatrix(matrix); + mask->fillPath(path); + auto pixelBuffer = std::static_pointer_cast(mask)->getBuffer(); + std::string pathMD5 = DumpMD5(pixelBuffer); + json rasterizerJson = {{"rasterizer_path", pathMD5}}; + auto pathCompareMD5 = PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_path"]; + std::string imagePath = "../test/out/rasterizer_path.png"; + TraceIf(pixelBuffer, imagePath, pathMD5 != pathCompareMD5); + EXPECT_EQ(pathCompareMD5.get(), pathMD5); - auto device = NativeGLDevice::Make(); - ASSERT_TRUE(device != nullptr); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto texture = mask->makeTexture(context); - ASSERT_TRUE(texture != nullptr); - auto surface = Surface::Make(context, mask->width(), mask->height()); - ASSERT_TRUE(surface != nullptr); - auto canvas = surface->getCanvas(); - canvas->drawTexture(texture.get()); - Bitmap bitmap = {}; - auto result = bitmap.allocPixels(mask->width(), mask->height(), true); - ASSERT_TRUE(result); - bitmap.eraseAll(); - auto pixels = bitmap.lockPixels(); - result = surface->readPixels(bitmap.info(), pixels); - bitmap.unlockPixels(); - ASSERT_TRUE(result); - device->unlock(); - std::string textureMD5 = DumpMD5(bitmap); - rasterizerJson["rasterizer_path_texture"] = textureMD5; - auto textureCompareMD5 = - PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_path_texture"]; - std::string texturePath = "../test/out/rasterizer_path_texture.png"; - TraceIf(bitmap, texturePath, textureMD5 != textureCompareMD5); - EXPECT_EQ(textureCompareMD5.get(), textureMD5); + auto device = NativeGLDevice::Make(); + ASSERT_TRUE(device != nullptr); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto texture = mask->makeTexture(context); + ASSERT_TRUE(texture != nullptr); + auto surface = Surface::Make(context, mask->width(), mask->height()); + ASSERT_TRUE(surface != nullptr); + auto canvas = surface->getCanvas(); + canvas->drawTexture(texture.get()); + Bitmap bitmap = {}; + auto result = bitmap.allocPixels(mask->width(), mask->height(), true); + ASSERT_TRUE(result); + bitmap.eraseAll(); + auto pixels = bitmap.lockPixels(); + result = surface->readPixels(bitmap.info(), pixels); + bitmap.unlockPixels(); + ASSERT_TRUE(result); + device->unlock(); + std::string textureMD5 = DumpMD5(bitmap); + rasterizerJson["rasterizer_path_texture"] = textureMD5; + auto textureCompareMD5 = + PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_path_texture"]; + std::string texturePath = "../test/out/rasterizer_path_texture.png"; + TraceIf(bitmap, texturePath, textureMD5 != textureCompareMD5); + EXPECT_EQ(textureCompareMD5.get(), textureMD5); - auto typeface = Typeface::MakeFromPath("../resources/font/NotoColorEmoji.ttf"); - ASSERT_TRUE(typeface != nullptr); - ASSERT_TRUE(typeface->hasColor()); - auto glyphID = typeface->getGlyphID("👻"); - ASSERT_TRUE(glyphID != 0); - Font font = {}; - font.setSize(300); - font.setTypeface(typeface); - font.setFauxItalic(true); - font.setFauxBold(true); - auto buffer = font.getGlyphImage(glyphID, &matrix); - ASSERT_TRUE(buffer != nullptr); - EXPECT_TRUE(fabsf(matrix.getScaleX() - 2.75229359f) < FLT_EPSILON); - EXPECT_TRUE(fabsf(matrix.getSkewX() + 0.550458729f) < FLT_EPSILON); - bitmap = Bitmap(std::static_pointer_cast(buffer)); - auto glyphMD5 = DumpMD5(bitmap); - rasterizerJson["rasterizer_glyph"] = glyphMD5; - auto glyphCompareMD5 = PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_glyph"]; - imagePath = "../test/out/rasterizer_emoji.png"; - TraceIf(bitmap, imagePath, glyphMD5 != glyphCompareMD5); - EXPECT_EQ(glyphCompareMD5.get(), glyphMD5); - PAGTestEnvironment::DumpJson["PAGRasterizerTest"] = rasterizerJson; + auto typeface = Typeface::MakeFromPath("../resources/font/NotoColorEmoji.ttf"); + ASSERT_TRUE(typeface != nullptr); + ASSERT_TRUE(typeface->hasColor()); + auto glyphID = typeface->getGlyphID("👻"); + ASSERT_TRUE(glyphID != 0); + Font font = {}; + font.setSize(300); + font.setTypeface(typeface); + font.setFauxItalic(true); + font.setFauxBold(true); + auto buffer = font.getGlyphImage(glyphID, &matrix); + ASSERT_TRUE(buffer != nullptr); + EXPECT_TRUE(fabsf(matrix.getScaleX() - 2.75229359f) < FLT_EPSILON); + EXPECT_TRUE(fabsf(matrix.getSkewX() + 0.550458729f) < FLT_EPSILON); + bitmap = Bitmap(std::static_pointer_cast(buffer)); + auto glyphMD5 = DumpMD5(bitmap); + rasterizerJson["rasterizer_glyph"] = glyphMD5; + auto glyphCompareMD5 = PAGTestEnvironment::CompareJson["PAGRasterizerTest"]["rasterizer_glyph"]; + imagePath = "../test/out/rasterizer_emoji.png"; + TraceIf(bitmap, imagePath, glyphMD5 != glyphCompareMD5); + EXPECT_EQ(glyphCompareMD5.get(), glyphMD5); + PAGTestEnvironment::DumpJson["PAGRasterizerTest"] = rasterizerJson; } } // namespace pag diff --git a/test/PAGSequenceTest.cpp b/test/PAGSequenceTest.cpp index d357375f56..a837414d7f 100644 --- a/test/PAGSequenceTest.cpp +++ b/test/PAGSequenceTest.cpp @@ -26,23 +26,23 @@ namespace pag { PAG_TEST_SUIT(PAGSequenceTest) void pagSequenceTest() { - auto pagFile = PAGFile::Load("../resources/apitest/wz_mvp.pag"); - EXPECT_NE(pagFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(750, 1334); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.5); - pagPlayer->flush(); - EXPECT_EQ(static_cast(pagPlayer->renderCache->sequenceCaches.size()), 1); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGSequenceTest"]["RenderOnScreen_ID80475733"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/wz_mvp.pag"); + EXPECT_NE(pagFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(750, 1334); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.5); + pagPlayer->flush(); + EXPECT_EQ(static_cast(pagPlayer->renderCache->sequenceCaches.size()), 1); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGSequenceTest"]["RenderOnScreen_ID80475733"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSequenceTest"]["RenderOnScreen_ID80475733"]; - TraceIf(pagSurface, "../test/out/RenderOnScreen_ID80475733.png", - compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSequenceTest"]["RenderOnScreen_ID80475733"]; + TraceIf(pagSurface, "../test/out/RenderOnScreen_ID80475733.png", + compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif } @@ -50,30 +50,30 @@ void pagSequenceTest() { * 用例描述: 测试直接上屏 */ PAG_TEST_F(PAGSequenceTest, RenderOnScreen_ID80475733) { - pagSequenceTest(); + pagSequenceTest(); } /** * 用例描述: bitmapSequence关键帧不是全屏的时候要清屏 */ PAG_TEST_F(PAGSequenceTest, BitmapSequenceReader_ID82681127) { - auto pagFile = PAGFile::Load("../resources/apitest/ZC_mg_seky2_landscape.pag"); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setProgress(0.5); - pagPlayer->flush(); - pagPlayer->setProgress(0.75); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGSequenceTest"]["BitmapSequenceReader_ID82681127"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/ZC_mg_seky2_landscape.pag"); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setProgress(0.5); + pagPlayer->flush(); + pagPlayer->setProgress(0.75); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGSequenceTest"]["BitmapSequenceReader_ID82681127"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = - PAGTestEnvironment::CompareJson["PAGSequenceTest"]["BitmapSequenceReader_ID82681127"]; - TraceIf(pagSurface, "../test/out/BitmapSequenceReader_ID82681127.png", - compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = + PAGTestEnvironment::CompareJson["PAGSequenceTest"]["BitmapSequenceReader_ID82681127"]; + TraceIf(pagSurface, "../test/out/BitmapSequenceReader_ID82681127.png", + compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif } @@ -81,21 +81,21 @@ PAG_TEST_F(PAGSequenceTest, BitmapSequenceReader_ID82681127) { * 用例描述: 视频序列帧作为遮罩 */ PAG_TEST_F(PAGSequenceTest, VideoSequenceAsMask_ID83191791) { - auto pagFile = PAGFile::Load("../resources/apitest/video_sequence_as_mask.pag"); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setProgress(0.2); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGSequenceTest"]["VideoSequenceAsMask_ID83191791"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/video_sequence_as_mask.pag"); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setProgress(0.2); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGSequenceTest"]["VideoSequenceAsMask_ID83191791"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = - PAGTestEnvironment::CompareJson["PAGSequenceTest"]["VideoSequenceAsMask_ID83191791"]; - TraceIf(pagSurface, "../test/out/VideoSequenceAsMask_ID83191791.png", - compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = + PAGTestEnvironment::CompareJson["PAGSequenceTest"]["VideoSequenceAsMask_ID83191791"]; + TraceIf(pagSurface, "../test/out/VideoSequenceAsMask_ID83191791.png", + compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif } } // namespace pag diff --git a/test/PAGSimplePathTest.cpp b/test/PAGSimplePathTest.cpp index 3e7ec0c391..956704dbd8 100644 --- a/test/PAGSimplePathTest.cpp +++ b/test/PAGSimplePathTest.cpp @@ -29,20 +29,20 @@ PAG_TEST_SUIT(PAGSimplePathTest) * 用例描述: 测试 shader 绘制椭圆 */ PAG_TEST_F(PAGSimplePathTest, TestRRect_ID86088211) { - auto pagFile = PAGFile::Load("../resources/apitest/ellipse.pag"); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGSimplePathTest"]["TestRRect_ID86088211"] = md5; + auto pagFile = PAGFile::Load("../resources/apitest/ellipse.pag"); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGSimplePathTest"]["TestRRect_ID86088211"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSimplePathTest"]["TestRRect_ID86088211"]; - TraceIf(pagSurface, "../test/out/TestRRect_ID86088211.png", compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSimplePathTest"]["TestRRect_ID86088211"]; + TraceIf(pagSurface, "../test/out/TestRRect_ID86088211.png", compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif } } // namespace pag diff --git a/test/PAGSmokeTest.cpp b/test/PAGSmokeTest.cpp index f4f126e306..ba23430e77 100644 --- a/test/PAGSmokeTest.cpp +++ b/test/PAGSmokeTest.cpp @@ -32,71 +32,71 @@ using nlohmann::json; * 用例描述: smoke文件夹下文件是否渲染正常 */ PAG_TEST(PAGSmokeTest, TestMD5) { - json dumpJson; - json compareJson; - //这里需要生成冒烟测试的md5 - std::ifstream inputFile("../test/res/smoke_md5_dump.json"); - bool needCompare; - if (inputFile) { - needCompare = true; - inputFile >> compareJson; - } + json dumpJson; + json compareJson; + //这里需要生成冒烟测试的md5 + std::ifstream inputFile("../test/res/smoke_md5_dump.json"); + bool needCompare; + if (inputFile) { + needCompare = true; + inputFile >> compareJson; + } - std::vector files; - GetAllPAGFiles("../resources/smoke", files); + std::vector files; + GetAllPAGFiles("../resources/smoke", files); - int size = static_cast(files.size()); - for (int i = 0; i < size; i++) { - auto fileName = files[i].substr(files[i].rfind("/") + 1, files[i].size()); - std::vector compareVector; + int size = static_cast(files.size()); + for (int i = 0; i < size; i++) { + auto fileName = files[i].substr(files[i].rfind("/") + 1, files[i].size()); + std::vector compareVector; - bool needCompareThis = false; - if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { - compareVector = compareJson[fileName].get>(); - needCompareThis = true; - } + bool needCompareThis = false; + if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { + compareVector = compareJson[fileName].get>(); + needCompareThis = true; + } - auto TestPAGFile = PAGFile::Load(files[i]); - ASSERT_NE(TestPAGFile, nullptr); - auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(TestPAGFile); + auto TestPAGFile = PAGFile::Load(files[i]); + ASSERT_NE(TestPAGFile, nullptr); + auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(TestPAGFile); - Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); - Frame currentFrame = 0; + Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); + Frame currentFrame = 0; - std::vector md5Vector; - std::string errorMsg = ""; + std::vector md5Vector; + std::string errorMsg = ""; - bool status = true; - while (currentFrame < totalFrames) { - //添加0.1帧目的是保证progress不会由于精度问题帧数计算错误,frame应该使用totalFrames作为总体帧数。因为对于file来说总时长为[0,totalFrames],对应于[0,1],因此归一化时,分母应该为totalFrames - pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); - pagPlayer->flush(); + bool status = true; + while (currentFrame < totalFrames) { + //添加0.1帧目的是保证progress不会由于精度问题帧数计算错误,frame应该使用totalFrames作为总体帧数。因为对于file来说总时长为[0,totalFrames],对应于[0,1],因此归一化时,分母应该为totalFrames + pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); + pagPlayer->flush(); - auto skImage = MakeSnapshot(pagSurface); - std::string md5 = DumpMD5(skImage); - md5Vector.push_back(md5); - if (needCompareThis && compareVector[currentFrame] != md5) { - errorMsg += (std::to_string(currentFrame) + ";"); - if (status) { - std::string imagePath = - "../test/out/smoke/" + fileName + "_" + std::to_string(currentFrame) + ".png"; - Trace(skImage, imagePath); - status = false; + auto skImage = MakeSnapshot(pagSurface); + std::string md5 = DumpMD5(skImage); + md5Vector.push_back(md5); + if (needCompareThis && compareVector[currentFrame] != md5) { + errorMsg += (std::to_string(currentFrame) + ";"); + if (status) { + std::string imagePath = + "../test/out/smoke/" + fileName + "_" + std::to_string(currentFrame) + ".png"; + Trace(skImage, imagePath); + status = false; + } + } + currentFrame++; } - } - currentFrame++; + EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; + dumpJson[fileName] = md5Vector; + EXPECT_EQ(errorMsg, "") << dumpJson; } - EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; - dumpJson[fileName] = md5Vector; - EXPECT_EQ(errorMsg, "") << dumpJson; - } - std::ofstream outFile("../test/out/smoke/smoke_md5_dump.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); + std::ofstream outFile("../test/out/smoke/smoke_md5_dump.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); } } // namespace pag diff --git a/test/PAGSolidLayerTest.cpp b/test/PAGSolidLayerTest.cpp index 6f48f07b43..9a743a8c72 100644 --- a/test/PAGSolidLayerTest.cpp +++ b/test/PAGSolidLayerTest.cpp @@ -30,20 +30,20 @@ PAG_TEST_SUIT(PAGSolidLayerTest) * 用例描述: PAGSolidLayerTest基础功能 */ PAG_TEST_F(PAGSolidLayerTest, SolidColor) { - int targetIndex = 0; - TestPAGFile->setCurrentTime(1.5 * 1000); - auto layer = GetLayer(TestPAGFile, LayerType::Solid, targetIndex); - ASSERT_NE(layer, nullptr) << "don't find solidLayer" << std::endl; - auto solidLayer = std::static_pointer_cast(layer); - ASSERT_TRUE(solidLayer->solidColor() == Green); - solidLayer->setSolidColor(Red); - ASSERT_EQ(Red, solidLayer->solidColor()); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGSolidLayerTest"] = {{"SolidColor", md5}}; + int targetIndex = 0; + TestPAGFile->setCurrentTime(1.5 * 1000); + auto layer = GetLayer(TestPAGFile, LayerType::Solid, targetIndex); + ASSERT_NE(layer, nullptr) << "don't find solidLayer" << std::endl; + auto solidLayer = std::static_pointer_cast(layer); + ASSERT_TRUE(solidLayer->solidColor() == Green); + solidLayer->setSolidColor(Red); + ASSERT_EQ(Red, solidLayer->solidColor()); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGSolidLayerTest"] = {{"SolidColor", md5}}; #ifdef COMPARE_JSON_PATH - auto colorJson = PAGTestEnvironment::CompareJson["PAGSolidLayerTest"]["SolidColor"]; - ASSERT_EQ(colorJson.get(), md5); + auto colorJson = PAGTestEnvironment::CompareJson["PAGSolidLayerTest"]["SolidColor"]; + ASSERT_EQ(colorJson.get(), md5); #endif } diff --git a/test/PAGSurfaceTest.cpp b/test/PAGSurfaceTest.cpp index c374b9c91b..489be68d4e 100644 --- a/test/PAGSurfaceTest.cpp +++ b/test/PAGSurfaceTest.cpp @@ -30,96 +30,96 @@ PAG_TEST_SUIT(PAGSurfaceTest) * 用例描述: 测试 PAGSurface 数据同步 */ PAG_TEST(PAGSurfaceTest, FromTexture_ID82382683) { - auto pagFile = PAGFile::Load("../resources/apitest/test.pag"); - int width = pagFile->width(); - int height = pagFile->height(); - auto device = NativeGLDevice::Make(); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto gl = GLContext::Unwrap(context); - auto glVersion = gl->caps->version; - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto backendTexture = BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); - auto nativeHandle = NativeGLDevice::GetCurrentNativeHandle(); - device->unlock(); - auto glDevice = std::static_pointer_cast(pagSurface->drawable->getDevice()); - EXPECT_TRUE(glDevice->sharableWith(nativeHandle)); + auto pagFile = PAGFile::Load("../resources/apitest/test.pag"); + int width = pagFile->width(); + int height = pagFile->height(); + auto device = NativeGLDevice::Make(); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto gl = GLContext::Unwrap(context); + auto glVersion = gl->caps->version; + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto backendTexture = BackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::TopLeft); + auto nativeHandle = NativeGLDevice::GetCurrentNativeHandle(); + device->unlock(); + auto glDevice = std::static_pointer_cast(pagSurface->drawable->getDevice()); + EXPECT_TRUE(glDevice->sharableWith(nativeHandle)); - auto drawable = std::make_shared(device, backendTexture, ImageOrigin::TopLeft); - auto pagSurface2 = PAGSurface::MakeFrom(drawable); - auto pagPlayer2 = std::make_shared(); - pagPlayer2->setSurface(pagSurface2); - pagPlayer2->setComposition(pagFile); - pagPlayer2->setProgress(0.1); - BackendSemaphore semaphore; - EXPECT_FALSE(pagPlayer2->wait(semaphore)); - semaphore.initGL(nullptr); - EXPECT_FALSE(pagPlayer2->wait(semaphore)); - semaphore = {}; - pagPlayer2->flushAndSignalSemaphore(&semaphore); - if (glVersion < GL_VER(3, 0)) { - EXPECT_FALSE(semaphore.isInitialized()); - } else { - EXPECT_TRUE(semaphore.isInitialized()); - EXPECT_NE(semaphore.glSync(), nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setComposition(pagFile); - pagPlayer->setSurface(pagSurface); - pagPlayer->setProgress(0.3); - EXPECT_TRUE(pagPlayer->wait(semaphore)); + auto drawable = std::make_shared(device, backendTexture, ImageOrigin::TopLeft); + auto pagSurface2 = PAGSurface::MakeFrom(drawable); + auto pagPlayer2 = std::make_shared(); + pagPlayer2->setSurface(pagSurface2); + pagPlayer2->setComposition(pagFile); + pagPlayer2->setProgress(0.1); + BackendSemaphore semaphore; + EXPECT_FALSE(pagPlayer2->wait(semaphore)); + semaphore.initGL(nullptr); + EXPECT_FALSE(pagPlayer2->wait(semaphore)); semaphore = {}; - pagPlayer->flushAndSignalSemaphore(&semaphore); - EXPECT_TRUE(semaphore.isInitialized()); - EXPECT_NE(semaphore.glSync(), nullptr); - EXPECT_TRUE(pagPlayer2->wait(semaphore)); - auto md5 = DumpMD5(pagSurface2); - PAGTestEnvironment::DumpJson["PAGSurfaceTest"]["FromTexture_ID82382683"] = md5; + pagPlayer2->flushAndSignalSemaphore(&semaphore); + if (glVersion < GL_VER(3, 0)) { + EXPECT_FALSE(semaphore.isInitialized()); + } else { + EXPECT_TRUE(semaphore.isInitialized()); + EXPECT_NE(semaphore.glSync(), nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setComposition(pagFile); + pagPlayer->setSurface(pagSurface); + pagPlayer->setProgress(0.3); + EXPECT_TRUE(pagPlayer->wait(semaphore)); + semaphore = {}; + pagPlayer->flushAndSignalSemaphore(&semaphore); + EXPECT_TRUE(semaphore.isInitialized()); + EXPECT_NE(semaphore.glSync(), nullptr); + EXPECT_TRUE(pagPlayer2->wait(semaphore)); + auto md5 = DumpMD5(pagSurface2); + PAGTestEnvironment::DumpJson["PAGSurfaceTest"]["FromTexture_ID82382683"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceTest"]["FromTexture_ID82382683"]; - TraceIf(pagSurface2, "../test/out/FromTexture_ID82382683.png", md5 != compareMD5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceTest"]["FromTexture_ID82382683"]; + TraceIf(pagSurface2, "../test/out/FromTexture_ID82382683.png", md5 != compareMD5); + EXPECT_EQ(compareMD5.get(), md5); #endif - } + } } /** * 用例描述: 遮罩使用屏幕坐标系时origin不一致的情况 */ PAG_TEST(PAGSurfaceTest, mask_ID85767971) { - auto pagFile = PAGFile::Load("../assets/test2.pag"); - auto width = pagFile->width(); - auto height = pagFile->height(); - auto device = NativeGLDevice::Make(); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto gl = GLContext::Unwrap(context); - GLTextureInfo textureInfo; - CreateTexture(gl, width, height, &textureInfo); - auto backendTexture = BackendTexture(textureInfo, width, height); - auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); - device->unlock(); + auto pagFile = PAGFile::Load("../assets/test2.pag"); + auto width = pagFile->width(); + auto height = pagFile->height(); + auto device = NativeGLDevice::Make(); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto gl = GLContext::Unwrap(context); + GLTextureInfo textureInfo; + CreateTexture(gl, width, height, &textureInfo); + auto backendTexture = BackendTexture(textureInfo, width, height); + auto pagSurface = PAGSurface::MakeFrom(backendTexture, ImageOrigin::BottomLeft); + device->unlock(); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(pagFile); - pagPlayer->setMatrix(Matrix::I()); - pagPlayer->setProgress(0.9); - pagPlayer->flush(); - auto md5 = DumpMD5(pagSurface); - PAGTestEnvironment::DumpJson["PAGSurfaceTest"]["mask_ID85767971"] = md5; + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(pagFile); + pagPlayer->setMatrix(Matrix::I()); + pagPlayer->setProgress(0.9); + pagPlayer->flush(); + auto md5 = DumpMD5(pagSurface); + PAGTestEnvironment::DumpJson["PAGSurfaceTest"]["mask_ID85767971"] = md5; #ifdef COMPARE_JSON_PATH - auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceTest"]["mask_ID85767971"]; - auto path = "../test/out/mask_ID85767971.png"; - TraceIf(pagSurface, path, compareMD5.get() != md5); - EXPECT_EQ(compareMD5.get(), md5); + auto compareMD5 = PAGTestEnvironment::CompareJson["PAGSurfaceTest"]["mask_ID85767971"]; + auto path = "../test/out/mask_ID85767971.png"; + TraceIf(pagSurface, path, compareMD5.get() != md5); + EXPECT_EQ(compareMD5.get(), md5); #endif - context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - gl = GLContext::Unwrap(context); - gl->deleteTextures(1, &textureInfo.id); - device->unlock(); + context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + gl = GLContext::Unwrap(context); + gl->deleteTextures(1, &textureInfo.id); + device->unlock(); } } // namespace pag diff --git a/test/PAGTextLayerTest.cpp b/test/PAGTextLayerTest.cpp index a5be09fa5d..b92b586e95 100644 --- a/test/PAGTextLayerTest.cpp +++ b/test/PAGTextLayerTest.cpp @@ -34,25 +34,25 @@ PAG_TEST_SUIT(PAGTextLayerTest) * 用例描述: PAGTextLayerTest fillColor 接口测试 */ PAG_TEST_F(PAGTextLayerTest, fillColor) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto layer = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; - auto textLayer = std::static_pointer_cast(layer); - auto fillColor = textLayer->fillColor(); - EXPECT_TRUE(fillColor == Blue); - TestPAGPlayer->flush(); - auto fillColorMd5 = getMd5FromSnap(); - ASSERT_NE(fillColorMd5, ""); - // 色值限定uint_8输入,天然合法 - textLayer->setFillColor(Red); - EXPECT_TRUE((textLayer->fillColor() == Red)); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["fillColorMd5"] = fillColorMd5; + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto layer = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; + auto textLayer = std::static_pointer_cast(layer); + auto fillColor = textLayer->fillColor(); + EXPECT_TRUE(fillColor == Blue); + TestPAGPlayer->flush(); + auto fillColorMd5 = getMd5FromSnap(); + ASSERT_NE(fillColorMd5, ""); + // 色值限定uint_8输入,天然合法 + textLayer->setFillColor(Red); + EXPECT_TRUE((textLayer->fillColor() == Red)); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["fillColorMd5"] = fillColorMd5; #ifdef COMPARE_JSON_PATH - auto cFillColor = - PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["fillColorMd5"]; - EXPECT_EQ(cFillColor.get(), fillColorMd5); + auto cFillColor = + PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["fillColorMd5"]; + EXPECT_EQ(cFillColor.get(), fillColorMd5); #endif } @@ -60,25 +60,25 @@ PAG_TEST_F(PAGTextLayerTest, fillColor) { * 用例描述: PAGTextLayerTest strokeColor 接口测试 */ PAG_TEST_F(PAGTextLayerTest, strokeColor) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto layer = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; - auto textLayer = std::static_pointer_cast(layer); - auto strokeColor = textLayer->strokeColor(); - EXPECT_TRUE((strokeColor == Red)); - TestPAGPlayer->flush(); - auto strokeColorMd5 = getMd5FromSnap(); - ASSERT_NE(strokeColorMd5, ""); - textLayer->setStrokeColor(Blue); - EXPECT_TRUE((textLayer->strokeColor() == Blue)); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["strokeColorMd5"] = - strokeColorMd5; + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto layer = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; + auto textLayer = std::static_pointer_cast(layer); + auto strokeColor = textLayer->strokeColor(); + EXPECT_TRUE((strokeColor == Red)); + TestPAGPlayer->flush(); + auto strokeColorMd5 = getMd5FromSnap(); + ASSERT_NE(strokeColorMd5, ""); + textLayer->setStrokeColor(Blue); + EXPECT_TRUE((textLayer->strokeColor() == Blue)); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["strokeColorMd5"] = + strokeColorMd5; #ifdef COMPARE_JSON_PATH - auto cStrokeColor = - PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["strokeColorMd5"]; - EXPECT_EQ(cStrokeColor.get(), strokeColorMd5); + auto cStrokeColor = + PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["strokeColorMd5"]; + EXPECT_EQ(cStrokeColor.get(), strokeColorMd5); #endif } @@ -86,53 +86,53 @@ PAG_TEST_F(PAGTextLayerTest, strokeColor) { * 用例描述: PAGTextLayerTest fontSize 接口测试 */ PAG_TEST_F(PAGTextLayerTest, fontSize) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto layer = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; - auto textLayer = std::static_pointer_cast(layer); - auto fontSize = textLayer->fontSize(); - EXPECT_EQ(fontSize, 60); - // 异常fontSize - textLayer->setFontSize(-30); - TestPAGPlayer->flush(); - textLayer->setFontSize(0); - TestPAGPlayer->flush(); - // 正常fontSize setter and getter - textLayer->setFontSize(80); - EXPECT_EQ(textLayer->fontSize(), 80); + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto layer = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; + auto textLayer = std::static_pointer_cast(layer); + auto fontSize = textLayer->fontSize(); + EXPECT_EQ(fontSize, 60); + // 异常fontSize + textLayer->setFontSize(-30); + TestPAGPlayer->flush(); + textLayer->setFontSize(0); + TestPAGPlayer->flush(); + // 正常fontSize setter and getter + textLayer->setFontSize(80); + EXPECT_EQ(textLayer->fontSize(), 80); } /** * 用例描述: PAGTextLayerTest text 接口测试 */ PAG_TEST_F(PAGTextLayerTest, text) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto layer = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; - auto textLayer = std::static_pointer_cast(layer); - auto text = textLayer->text(); - EXPECT_EQ(text, "文本图层1"); + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto layer = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; + auto textLayer = std::static_pointer_cast(layer); + auto text = textLayer->text(); + EXPECT_EQ(text, "文本图层1"); } /** * 用例描述: PAGTextLayerTest textDocumentMd5 接口测试 */ PAG_TEST_F(PAGTextLayerTest, textDocumentMd5) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - TestPAGPlayer->flush(); - auto textDocumentMd5 = getMd5FromSnap(); - ASSERT_NE(textDocumentMd5, ""); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["textDocumentMd5"] = - textDocumentMd5; + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + TestPAGPlayer->flush(); + auto textDocumentMd5 = getMd5FromSnap(); + ASSERT_NE(textDocumentMd5, ""); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["TextLayer"]["textDocumentMd5"] = + textDocumentMd5; #ifdef COMPARE_JSON_PATH - auto cText = - PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["textDocumentMd5"]; - EXPECT_EQ(cText.get(), textDocumentMd5); + auto cText = + PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["TextLayer"]["textDocumentMd5"]; + EXPECT_EQ(cText.get(), textDocumentMd5); #endif } @@ -140,75 +140,75 @@ PAG_TEST_F(PAGTextLayerTest, textDocumentMd5) { * 用例描述: PAGTextLayerTest多线程修改测试 */ PAG_TEST_F(PAGTextLayerTest, multiThreadModify) { - ASSERT_NE(TestPAGFile, nullptr); - TestPAGFile->setCurrentTime(5 * 1000000); - int target = 0; - auto layer = GetLayer(TestPAGFile, LayerType::Text, target); - ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; - auto textLayer = std::static_pointer_cast(layer); + ASSERT_NE(TestPAGFile, nullptr); + TestPAGFile->setCurrentTime(5 * 1000000); + int target = 0; + auto layer = GetLayer(TestPAGFile, LayerType::Text, target); + ASSERT_NE(layer, nullptr) << "not get a textLayer" << std::endl; + auto textLayer = std::static_pointer_cast(layer); - // 多线程替换文本 - std::thread thread1([textLayer]() { - for (int i = 0; i < 10; ++i) { - std::cout << "线程1 present" << std::endl; - TestPAGPlayer->flush(); - } - }); + // 多线程替换文本 + std::thread thread1([textLayer]() { + for (int i = 0; i < 10; ++i) { + std::cout << "线程1 present" << std::endl; + TestPAGPlayer->flush(); + } + }); - std::thread thread2([textLayer]() { - for (int i = 0; i < 10; ++i) { - std::cout << "线程2替换文本" << std::endl; - textLayer->setFontSize(20); - textLayer->setFillColor(Blue); - textLayer->setText("线程222替换文本"); - TestPAGPlayer->flush(); - } - }); + std::thread thread2([textLayer]() { + for (int i = 0; i < 10; ++i) { + std::cout << "线程2替换文本" << std::endl; + textLayer->setFontSize(20); + textLayer->setFillColor(Blue); + textLayer->setText("线程222替换文本"); + TestPAGPlayer->flush(); + } + }); - thread1.join(); - thread2.join(); - textLayer->setText("替换文本666666"); - TestPAGPlayer->flush(); + thread1.join(); + thread2.join(); + textLayer->setText("替换文本666666"); + TestPAGPlayer->flush(); } /** * 用例描述: PAGTextLayer Make 功能测试 */ PAG_TEST_F(PAGTextLayerTest, Make) { - auto textLayer = PAGTextLayer::Make(0, ""); - EXPECT_TRUE(textLayer == nullptr); - textLayer = PAGTextLayer::Make(10, std::shared_ptr{}); - EXPECT_TRUE(textLayer == nullptr); - textLayer = PAGTextLayer::Make(6000000, "PAGTextLayerMakeTest", 30); - EXPECT_TRUE(textLayer != nullptr); - EXPECT_TRUE(textLayer->getLayer()->transform->position->value.y == 30); - EXPECT_TRUE(textLayer->duration() == 6000000); - EXPECT_TRUE(textLayer->text() == "PAGTextLayerMakeTest"); - EXPECT_TRUE(textLayer->fontSize() == 30); + auto textLayer = PAGTextLayer::Make(0, ""); + EXPECT_TRUE(textLayer == nullptr); + textLayer = PAGTextLayer::Make(10, std::shared_ptr {}); + EXPECT_TRUE(textLayer == nullptr); + textLayer = PAGTextLayer::Make(6000000, "PAGTextLayerMakeTest", 30); + EXPECT_TRUE(textLayer != nullptr); + EXPECT_TRUE(textLayer->getLayer()->transform->position->value.y == 30); + EXPECT_TRUE(textLayer->duration() == 6000000); + EXPECT_TRUE(textLayer->text() == "PAGTextLayerMakeTest"); + EXPECT_TRUE(textLayer->fontSize() == 30); } /** * 用例描述: PAGTextLayer Emoji 功能测试 */ PAG_TEST_F(PAGTextLayerTest, Emoji_ID79762747) { - auto pagFile = PAGFile::Load("../assets/zongyi2.pag"); - auto textData = pagFile->getTextData(0); - // 自动化测试里屏蔽了 mac 端原生的字体库改用 freetype,防止自动化测试过程总是弹出 - // 字体下载的窗口阻塞测试。 但是 freetype 用于测量 mac 端的字体,比如 Emoji - // 时,会出现位置偏上的情况。但是只影响到 自动化测试, Android 和 iOS - // 端以及其他平台都是正常的。可以作为已知问题忽略。 - textData->text = "ha ha哈哈\n哈😆哈哈哈"; - pagFile->replaceText(0, textData); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["emoji"] = md5; + auto pagFile = PAGFile::Load("../assets/zongyi2.pag"); + auto textData = pagFile->getTextData(0); + // 自动化测试里屏蔽了 mac 端原生的字体库改用 freetype,防止自动化测试过程总是弹出 + // 字体下载的窗口阻塞测试。 但是 freetype 用于测量 mac 端的字体,比如 Emoji + // 时,会出现位置偏上的情况。但是只影响到 自动化测试, Android 和 iOS + // 端以及其他平台都是正常的。可以作为已知问题忽略。 + textData->text = "ha ha哈哈\n哈😆哈哈哈"; + pagFile->replaceText(0, textData); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["emoji"] = md5; #ifdef COMPARE_JSON_PATH - auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["emoji"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_emoji.png", - emojiMd5.get() != md5); - EXPECT_EQ(emojiMd5.get(), md5); + auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["emoji"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_emoji.png", + emojiMd5.get() != md5); + EXPECT_EQ(emojiMd5.get(), md5); #endif } @@ -216,20 +216,20 @@ PAG_TEST_F(PAGTextLayerTest, Emoji_ID79762747) { * 用例描述: PAGTextLayer Emoji 功能测试 */ PAG_TEST_F(PAGTextLayerTest, NormalEmoji_ID79762751) { - auto pagFile = PAGFile::Load("../assets/test2.pag"); - auto textData = pagFile->getTextData(0); - textData->text = "ha ha哈哈\n哈😆哈哈哈"; - pagFile->replaceText(0, textData); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["normalEmoji"] = md5; + auto pagFile = PAGFile::Load("../assets/test2.pag"); + auto textData = pagFile->getTextData(0); + textData->text = "ha ha哈哈\n哈😆哈哈哈"; + pagFile->replaceText(0, textData); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["normalEmoji"] = md5; #ifdef COMPARE_JSON_PATH - auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["normalEmoji"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_normalEmoji.png", - emojiMd5.get() != md5); - EXPECT_EQ(emojiMd5.get(), md5); + auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["normalEmoji"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_normalEmoji.png", + emojiMd5.get() != md5); + EXPECT_EQ(emojiMd5.get(), md5); #endif } @@ -237,20 +237,20 @@ PAG_TEST_F(PAGTextLayerTest, NormalEmoji_ID79762751) { * 用例描述: 测试文字替换 */ PAG_TEST_F(PAGTextLayerTest, text_ID83312235) { - auto pagFile = PAGFile::Load("../assets/test2.pag"); - auto textData = pagFile->getTextData(0); - textData->text = "ha ha哈哈\n哈哈哈哈"; - textData->justification = ParagraphJustification::LeftJustify; - pagFile->replaceText(0, textData); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["text_ID83312235"] = md5; + auto pagFile = PAGFile::Load("../assets/test2.pag"); + auto textData = pagFile->getTextData(0); + textData->text = "ha ha哈哈\n哈哈哈哈"; + textData->justification = ParagraphJustification::LeftJustify; + pagFile->replaceText(0, textData); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["text_ID83312235"] = md5; #ifdef COMPARE_JSON_PATH - auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["text_ID83312235"]; - TraceIf(TestPAGSurface, "../test/out/text_ID83312235.png", emojiMd5.get() != md5); - EXPECT_EQ(emojiMd5.get(), md5); + auto emojiMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["text_ID83312235"]; + TraceIf(TestPAGSurface, "../test/out/text_ID83312235.png", emojiMd5.get() != md5); + EXPECT_EQ(emojiMd5.get(), md5); #endif } @@ -258,17 +258,17 @@ PAG_TEST_F(PAGTextLayerTest, text_ID83312235) { * 用例描述: PAGTextLayer 竖排文本 功能测试 */ PAG_TEST_F(PAGTextLayerTest, VerticalText_ID80511765) { - auto pagFile = PAGFile::Load("../assets/TextDirection.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textDirection"] = md5; + auto pagFile = PAGFile::Load("../assets/TextDirection.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textDirection"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textDirection"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_textDirection.png", - textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textDirection"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_textDirection.png", + textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -276,17 +276,17 @@ PAG_TEST_F(PAGTextLayerTest, VerticalText_ID80511765) { * 用例描述: PAGTextLayer 字间距动画 横排文本 背景框 功能测试 */ PAG_TEST_F(PAGTextLayerTest, TrackingAnimator_ID859317799) { - auto pagFile = PAGFile::Load("../assets/TrackingAnimator.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["trackingAnimator"] = md5; + auto pagFile = PAGFile::Load("../assets/TrackingAnimator.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["trackingAnimator"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["trackingAnimator"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_trackingAnimator.png", - textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["trackingAnimator"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_trackingAnimator.png", + textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -294,17 +294,17 @@ PAG_TEST_F(PAGTextLayerTest, TrackingAnimator_ID859317799) { * 用例描述: PAGTextLayer 字间距动画 竖排文本 功能测试 */ PAG_TEST_F(PAGTextLayerTest, TrackingAnimatorVertical_ID859317799) { - auto pagFile = PAGFile::Load("../assets/TrackingAnimatorVertical.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["trackingAnimatorVertical"] = md5; + auto pagFile = PAGFile::Load("../assets/TrackingAnimatorVertical.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["trackingAnimatorVertical"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["trackingAnimatorVertical"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_trackingAnimatorVertical.png", - textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["trackingAnimatorVertical"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_trackingAnimatorVertical.png", + textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -312,17 +312,17 @@ PAG_TEST_F(PAGTextLayerTest, TrackingAnimatorVertical_ID859317799) { * 用例描述: PAGTextLayer 位置动画 */ PAG_TEST_F(PAGTextLayerTest, PositionAnimator_ID859317799) { - auto pagFile = PAGFile::Load("../assets/TextPositionAnimator.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["positionAnimator"] = md5; + auto pagFile = PAGFile::Load("../assets/TextPositionAnimator.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["positionAnimator"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["positionAnimator"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_positionAnimator.png", - textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["positionAnimator"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_positionAnimator.png", + textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -330,17 +330,17 @@ PAG_TEST_F(PAGTextLayerTest, PositionAnimator_ID859317799) { * 用例描述: PAGTextLayer 文本动画 */ PAG_TEST_F(PAGTextLayerTest, TextAnimators_ID863204853) { - auto pagFile = PAGFile::Load("../assets/TextAnimators.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimators"] = md5; + auto pagFile = PAGFile::Load("../assets/TextAnimators.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimators"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimators"]; - TraceIf(TestPAGSurface, "../test/out/pag_textlayer_textAnimators.png", - textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimators"]; + TraceIf(TestPAGSurface, "../test/out/pag_textlayer_textAnimators.png", + textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -348,71 +348,71 @@ PAG_TEST_F(PAGTextLayerTest, TextAnimators_ID863204853) { * 用例描述: PAGTextLayer 文本动画 */ PAG_TEST_F(PAGTextLayerTest, TextAnimatorsMode_ID863204817) { - auto pagFile = PAGFile::Load("../assets/TextAnimatorMode.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorMode"] = md5; + auto pagFile = PAGFile::Load("../assets/TextAnimatorMode.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorMode"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorMode"]; - TraceIf(TestPAGSurface, "../test/out/textAnimatorMode.png", textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorMode"]; + TraceIf(TestPAGSurface, "../test/out/textAnimatorMode.png", textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif - auto file = pagFile->getFile(); - auto text = file->getTextAt(0); - bool hasBias = false; - auto position = TextAnimatorRenderer::GetPositionFromAnimators( - &text->animators, text->getTextDocument().get(), 0, 0, &hasBias); - EXPECT_EQ(hasBias, false); - EXPECT_EQ(position.x, 0.0f); - EXPECT_EQ(position.y, -180.0f); - float minAscent = 0.0f; - float maxDescent = 0.0f; - pag::CalculateTextAscentAndDescent(text->getTextDocument(), &minAscent, &maxDescent); - EXPECT_LE(fabs(minAscent - (-55.68f)), 0.01f); - EXPECT_LE(fabs(maxDescent - 13.824f), 0.01f); + auto file = pagFile->getFile(); + auto text = file->getTextAt(0); + bool hasBias = false; + auto position = TextAnimatorRenderer::GetPositionFromAnimators( + &text->animators, text->getTextDocument().get(), 0, 0, &hasBias); + EXPECT_EQ(hasBias, false); + EXPECT_EQ(position.x, 0.0f); + EXPECT_EQ(position.y, -180.0f); + float minAscent = 0.0f; + float maxDescent = 0.0f; + pag::CalculateTextAscentAndDescent(text->getTextDocument(), &minAscent, &maxDescent); + EXPECT_LE(fabs(minAscent - (-55.68f)), 0.01f); + EXPECT_LE(fabs(maxDescent - 13.824f), 0.01f); } /** * 用例描述: PAGTextLayer 文本动画 */ PAG_TEST_F(PAGTextLayerTest, TextAnimatorsX7_ID863204817) { - auto pagFile = PAGFile::Load("../assets/TextAnimatorX7.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorX7"] = md5; + auto pagFile = PAGFile::Load("../assets/TextAnimatorX7.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorX7"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorX7"]; - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorX7"]; + EXPECT_EQ(textMd5.get(), md5); #endif - auto bytes = Codec::Encode(pagFile->getFile()); - ASSERT_NE(bytes->data(), nullptr); - ASSERT_GT(static_cast(bytes->length()), 0); - auto newPagFile = PAGFile::Load(bytes->data(), bytes->length()); - TestPAGPlayer->setComposition(newPagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto newMd5 = getMd5FromSnap(); - EXPECT_EQ(newMd5, md5); + auto bytes = Codec::Encode(pagFile->getFile()); + ASSERT_NE(bytes->data(), nullptr); + ASSERT_GT(static_cast(bytes->length()), 0); + auto newPagFile = PAGFile::Load(bytes->data(), bytes->length()); + TestPAGPlayer->setComposition(newPagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto newMd5 = getMd5FromSnap(); + EXPECT_EQ(newMd5, md5); } /** * 用例描述: PAGTextLayer 文本动画 平滑 */ PAG_TEST_F(PAGTextLayerTest, TextAnimatorSmooth_ID863204817) { - auto pagFile = PAGFile::Load("../assets/TextAnimatorSmooth.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorSmooth"] = md5; + auto pagFile = PAGFile::Load("../assets/TextAnimatorSmooth.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + PAGTestEnvironment::DumpJson["PAGTextLayerTester"]["textAnimatorSmooth"] = md5; #ifdef COMPARE_JSON_PATH - auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorSmooth"]; - TraceIf(TestPAGSurface, "../test/out/textAnimatorSmooth.png", textMd5.get() != md5); - EXPECT_EQ(textMd5.get(), md5); + auto textMd5 = PAGTestEnvironment::CompareJson["PAGTextLayerTester"]["textAnimatorSmooth"]; + TraceIf(TestPAGSurface, "../test/out/textAnimatorSmooth.png", textMd5.get() != md5); + EXPECT_EQ(textMd5.get(), md5); #endif } @@ -420,72 +420,72 @@ PAG_TEST_F(PAGTextLayerTest, TextAnimatorSmooth_ID863204817) { * 用例描述: PAGTextLayer 文本Bounds获取-换行 */ PAG_TEST_F(PAGTextLayerTest, TextBounds) { - auto pagFile = PAGFile::Load("../assets/test2.pag"); - auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); - auto pagPlayer = new PAGPlayer(); - pagPlayer->setComposition(pagFile); - pagPlayer->setSurface(pagSurface); - pagPlayer->setProgress(0.5f); - pagPlayer->flush(); - auto textLayer = std::static_pointer_cast( - pagFile->getLayersByEditableIndex(0, LayerType::Text)[0]); - textLayer->setText( - "测试文本\n" - "\n" - "\n"); - pagPlayer->setProgress(0.5); - pagPlayer->flush(); - auto bounds = pagPlayer->getBounds(textLayer); - bounds.round(); - auto defaultBounds = Rect::MakeXYWH(361, 1465, 371, 329); - EXPECT_TRUE(bounds == defaultBounds); + auto pagFile = PAGFile::Load("../assets/test2.pag"); + auto pagSurface = PAGSurface::MakeOffscreen(pagFile->width(), pagFile->height()); + auto pagPlayer = new PAGPlayer(); + pagPlayer->setComposition(pagFile); + pagPlayer->setSurface(pagSurface); + pagPlayer->setProgress(0.5f); + pagPlayer->flush(); + auto textLayer = std::static_pointer_cast( + pagFile->getLayersByEditableIndex(0, LayerType::Text)[0]); + textLayer->setText( + "测试文本\n" + "\n" + "\n"); + pagPlayer->setProgress(0.5); + pagPlayer->flush(); + auto bounds = pagPlayer->getBounds(textLayer); + bounds.round(); + auto defaultBounds = Rect::MakeXYWH(361, 1465, 371, 329); + EXPECT_TRUE(bounds == defaultBounds); - textLayer->setText( - "测试文本\n" - "\n" - " "); - pagPlayer->flush(); - bounds = pagPlayer->getBounds(textLayer); - bounds.round(); - defaultBounds = Rect::MakeXYWH(361, 1465, 371, 310); - EXPECT_TRUE(bounds == defaultBounds); + textLayer->setText( + "测试文本\n" + "\n" + " "); + pagPlayer->flush(); + bounds = pagPlayer->getBounds(textLayer); + bounds.round(); + defaultBounds = Rect::MakeXYWH(361, 1465, 371, 310); + EXPECT_TRUE(bounds == defaultBounds); - textLayer->setText( - "测试文本\n" - "\n" - "T\n"); - pagPlayer->flush(); - bounds = pagPlayer->getBounds(textLayer); - bounds.round(); - EXPECT_TRUE(bounds == defaultBounds); + textLayer->setText( + "测试文本\n" + "\n" + "T\n"); + pagPlayer->flush(); + bounds = pagPlayer->getBounds(textLayer); + bounds.round(); + EXPECT_TRUE(bounds == defaultBounds); - textLayer->setText(" "); - pagPlayer->flush(); - bounds = pagPlayer->getBounds(textLayer); - bounds.round(); - defaultBounds = Rect::MakeXYWH(475, 1556, 134, 141); - EXPECT_TRUE(bounds == defaultBounds); + textLayer->setText(" "); + pagPlayer->flush(); + bounds = pagPlayer->getBounds(textLayer); + bounds.round(); + defaultBounds = Rect::MakeXYWH(475, 1556, 134, 141); + EXPECT_TRUE(bounds == defaultBounds); - delete pagPlayer; + delete pagPlayer; } /** * 用例描述: PAGTextLayer 文本Bounds获取-含有遮罩 */ PAG_TEST_F(PAGTextLayerTest, TrackMatteTextBounds) { - auto pagFile = PAGFile::Load("../assets/text_matte.pag"); - TestPAGPlayer->setComposition(pagFile); - TestPAGPlayer->setProgress(0.5f); - TestPAGPlayer->flush(); - auto defaultBounds = Rect::MakeXYWH(219, 485, 445, 112); - for (int i = 0; i < pagFile->numTexts(); i++) { - auto textLayers = pagFile->getLayersByEditableIndex(i, LayerType::Text); - for (const auto& textLayer : textLayers) { - auto bounds = TestPAGPlayer->getBounds(textLayer); - bounds.round(); - EXPECT_EQ(bounds == defaultBounds, true); + auto pagFile = PAGFile::Load("../assets/text_matte.pag"); + TestPAGPlayer->setComposition(pagFile); + TestPAGPlayer->setProgress(0.5f); + TestPAGPlayer->flush(); + auto defaultBounds = Rect::MakeXYWH(219, 485, 445, 112); + for (int i = 0; i < pagFile->numTexts(); i++) { + auto textLayers = pagFile->getLayersByEditableIndex(i, LayerType::Text); + for (const auto& textLayer : textLayers) { + auto bounds = TestPAGPlayer->getBounds(textLayer); + bounds.round(); + EXPECT_EQ(bounds == defaultBounds, true); + } } - } } } // namespace pag diff --git a/test/PAGTimeStretchTest.cpp b/test/PAGTimeStretchTest.cpp index 377c56e362..8093dece48 100644 --- a/test/PAGTimeStretchTest.cpp +++ b/test/PAGTimeStretchTest.cpp @@ -35,132 +35,132 @@ bool dumpStatus; PAG_TEST_SUIT(PAGTimeStrechTest) void initData() { - std::ifstream inputFile("../test/res/compare_timestretch_md5.json"); - if (inputFile) { - needCompare = true; - inputFile >> compareJson; - dumpJson = compareJson; - } + std::ifstream inputFile("../test/res/compare_timestretch_md5.json"); + if (inputFile) { + needCompare = true; + inputFile >> compareJson; + dumpJson = compareJson; + } } void saveFile() { - if (dumpStatus) { - std::ofstream outFile("../test/out/compare_timestretch_md5.json"); - outFile << std::setw(4) << dumpJson << std::endl; - outFile.close(); - } + if (dumpStatus) { + std::ofstream outFile("../test/out/compare_timestretch_md5.json"); + outFile << std::setw(4) << dumpJson << std::endl; + outFile.close(); + } } void TimeStretchTest(std::string path, float scaleFactor) { - std::vector shortenArray = {0, 6, 30, 59}; - std::vector stretchArray = {0, 12, 120, 239}; - - auto fileName = path.substr(path.rfind("/") + 1, path.size()); - std::vector compareVector; - - auto TestPAGFile = PAGFile::Load(path); - ASSERT_NE(TestPAGFile, nullptr); - int64_t duartion = TestPAGFile->duration(); - std::vector array; - - TestPAGFile->setDuration(duartion * scaleFactor); - if (scaleFactor < 1) { - fileName += "_shorten"; - array = shortenArray; - } else { - fileName += "_stretch"; - array = stretchArray; - } - - bool needCompareThis = false; - if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { - compareVector = compareJson[fileName].get>(); - needCompareThis = true; - } - - auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); - ASSERT_NE(pagSurface, nullptr); - auto pagPlayer = std::make_shared(); - pagPlayer->setSurface(pagSurface); - pagPlayer->setComposition(TestPAGFile); - - Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); - - std::vector md5Vector; - std::string errorMsg = ""; - - auto pagImage = PAGImage::FromPath("../resources/apitest/test_timestretch.png"); - TestPAGFile->replaceImage(0, pagImage); - - bool status = true; - int index = 0; - for (const auto& currentFrame : array) { - pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); - pagPlayer->getProgress(); - pagPlayer->flush(); - - auto skImage = MakeSnapshot(pagSurface); - - std::string md5 = DumpMD5(skImage); - md5Vector.push_back(md5); - if (needCompareThis && compareVector[index] != md5) { - errorMsg += (std::to_string(currentFrame) + ";"); - if (status) { - std::string imagePath = - "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; - Trace(skImage, imagePath); - status = false; - dumpStatus = true; - } + std::vector shortenArray = {0, 6, 30, 59}; + std::vector stretchArray = {0, 12, 120, 239}; + + auto fileName = path.substr(path.rfind("/") + 1, path.size()); + std::vector compareVector; + + auto TestPAGFile = PAGFile::Load(path); + ASSERT_NE(TestPAGFile, nullptr); + int64_t duartion = TestPAGFile->duration(); + std::vector array; + + TestPAGFile->setDuration(duartion * scaleFactor); + if (scaleFactor < 1) { + fileName += "_shorten"; + array = shortenArray; + } else { + fileName += "_stretch"; + array = stretchArray; + } + + bool needCompareThis = false; + if (needCompare && compareJson.contains(fileName) && compareJson[fileName].is_array()) { + compareVector = compareJson[fileName].get>(); + needCompareThis = true; + } + + auto pagSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); + ASSERT_NE(pagSurface, nullptr); + auto pagPlayer = std::make_shared(); + pagPlayer->setSurface(pagSurface); + pagPlayer->setComposition(TestPAGFile); + + Frame totalFrames = TimeToFrame(TestPAGFile->duration(), TestPAGFile->frameRate()); + + std::vector md5Vector; + std::string errorMsg = ""; + + auto pagImage = PAGImage::FromPath("../resources/apitest/test_timestretch.png"); + TestPAGFile->replaceImage(0, pagImage); + + bool status = true; + int index = 0; + for (const auto& currentFrame : array) { + pagPlayer->setProgress((currentFrame + 0.1) * 1.0 / totalFrames); + pagPlayer->getProgress(); + pagPlayer->flush(); + + auto skImage = MakeSnapshot(pagSurface); + + std::string md5 = DumpMD5(skImage); + md5Vector.push_back(md5); + if (needCompareThis && compareVector[index] != md5) { + errorMsg += (std::to_string(currentFrame) + ";"); + if (status) { + std::string imagePath = + "../test/out/" + fileName + "_" + std::to_string(currentFrame) + ".png"; + Trace(skImage, imagePath); + status = false; + dumpStatus = true; + } + } + index++; } - index++; - } - EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; - dumpJson[fileName] = md5Vector; + EXPECT_EQ(errorMsg, "") << fileName << " frame fail"; + dumpJson[fileName] = md5Vector; } /** * 用例描述: PAGTimeStrech渲染测试: Repeat模式-缩减 */ PAG_TEST_F(PAGTimeStrechTest, Repeat_Shorten_TestMD5) { - initData(); - TimeStretchTest("../resources/timestretch/repeat.pag", 0.5); + initData(); + TimeStretchTest("../resources/timestretch/repeat.pag", 0.5); } /** * 用例描述: PAGTimeStrech渲染测试: Repeat模式-拉伸 */ PAG_TEST_F(PAGTimeStrechTest, Repeat_Stretch_TestMD5) { - TimeStretchTest("../resources/timestretch/repeat.pag", 2); + TimeStretchTest("../resources/timestretch/repeat.pag", 2); } /** * 用例描述: PAGTimeStrech渲染测试-RepeatInverted-缩减 */ PAG_TEST_F(PAGTimeStrechTest, RepeatInverted_Shorten_TestMD5) { - TimeStretchTest("../resources/timestretch/repeatInverted.pag", 0.5); + TimeStretchTest("../resources/timestretch/repeatInverted.pag", 0.5); } /** * 用例描述: PAGTimeStrech渲染测试-RepeatInverted-拉伸 */ PAG_TEST_F(PAGTimeStrechTest, RepeatInverted_Stretch_TestMD5) { - TimeStretchTest("../resources/timestretch/repeatInverted.pag", 2); + TimeStretchTest("../resources/timestretch/repeatInverted.pag", 2); } /** * 用例描述: PAGTimeStrech渲染测试-Scale模式-缩减 */ PAG_TEST_F(PAGTimeStrechTest, Scale_Shorten_TestMD5) { - TimeStretchTest("../resources/timestretch/scale.pag", 0.5); + TimeStretchTest("../resources/timestretch/scale.pag", 0.5); } /** * 用例描述: PAGTimeStrech渲染测试: Scale模式-拉伸 */ PAG_TEST_F(PAGTimeStrechTest, Scale_Stretch_TestMD5) { - TimeStretchTest("../resources/timestretch/scale.pag", 2); - saveFile(); + TimeStretchTest("../resources/timestretch/scale.pag", 2); + saveFile(); } } // namespace pag diff --git a/test/PAGTimeUtilsTest.cpp b/test/PAGTimeUtilsTest.cpp index aee25e06cb..59fa474532 100644 --- a/test/PAGTimeUtilsTest.cpp +++ b/test/PAGTimeUtilsTest.cpp @@ -30,19 +30,19 @@ PAG_TEST_SUIT(PAGTimeUtilsTest) * 用例描述: 测试图层对时间的测试是否正确 */ PAG_TEST_F(PAGTimeUtilsTest, ConvertProgressAndFrame) { - auto duration = TestPAGFile->duration(); - auto frame = TimeToFrame(duration, TestPAGFile->frameRate()); - for (int i = 0; i <= frame * 2; i++) { - auto progress = i * 0.5 / frame; - TestPAGFile->setProgress(progress); - TestPAGPlayer->flush(); - auto md5 = getMd5FromSnap(); - progress = TestPAGFile->getProgress(); - TestPAGFile->setProgress(progress); - TestPAGPlayer->flush(); - auto md52 = getMd5FromSnap(); - ASSERT_EQ(md52, md5); - } + auto duration = TestPAGFile->duration(); + auto frame = TimeToFrame(duration, TestPAGFile->frameRate()); + for (int i = 0; i <= frame * 2; i++) { + auto progress = i * 0.5 / frame; + TestPAGFile->setProgress(progress); + TestPAGPlayer->flush(); + auto md5 = getMd5FromSnap(); + progress = TestPAGFile->getProgress(); + TestPAGFile->setProgress(progress); + TestPAGPlayer->flush(); + auto md52 = getMd5FromSnap(); + ASSERT_EQ(md52, md5); + } } } // namespace pag diff --git a/test/ReadPixelsTest.cpp b/test/ReadPixelsTest.cpp index c6ab1c03a3..0e30216b6a 100644 --- a/test/ReadPixelsTest.cpp +++ b/test/ReadPixelsTest.cpp @@ -43,270 +43,270 @@ using nlohmann::json; * 用例描述: 像素格式转换相关功能测试-PixelMap */ PAG_TEST(ReadPixelsTest, TestPixelMap) { - auto image = Image::MakeFrom("../resources/apitest/test_timestretch.png"); - EXPECT_TRUE(image != nullptr); - auto width = image->width(); - auto height = image->height(); - auto RGBAInfo = ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Unpremultiplied); - auto byteSize = RGBAInfo.byteSize(); - auto pixelsA = new uint8_t[byteSize]; - auto pixelsB = new uint8_t[byteSize]; - auto result = image->readPixels(RGBAInfo, pixelsA); - EXPECT_TRUE(result); - - json compareJson = PAGTestEnvironment::CompareJson["PixelMapTest"]; - json outputJson = {}; - - PixelMap RGBAMap(RGBAInfo, pixelsA); - CHECK_PIXELS(RGBAInfo, pixelsA, "PixelMap_RGBA_Original"); - - result = RGBAMap.readPixels(RGBAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_RGBA_to_RGBA"); - - memset(pixelsB, 0, RGBAInfo.byteSize()); - result = RGBAMap.readPixels(RGBAInfo, pixelsB, 100, 100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_RGBA_to_RGBA_100_100"); - - auto RGBARectInfo = ImageInfo::Make(500, 500, ColorType::RGBA_8888, AlphaType::Premultiplied); - memset(pixelsB, 0, RGBARectInfo.byteSize()); - result = RGBAMap.readPixels(RGBARectInfo, pixelsB, -100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixelsB, "PixelMap_RGBA_to_RGBA_-100_-100"); - - memset(pixelsB, 0, RGBARectInfo.byteSize()); - result = RGBAMap.readPixels(RGBARectInfo, pixelsB, 100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixelsB, "PixelMap_RGBA_to_RGBA_100_-100"); - - auto rgbAInfo = RGBAInfo.makeAlphaType(AlphaType::Premultiplied); - result = RGBAMap.readPixels(rgbAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(rgbAInfo, pixelsB, "PixelMap_RGBA_to_rgbA"); - - auto bgrAInfo = rgbAInfo.makeColorType(ColorType::BGRA_8888); - result = RGBAMap.readPixels(bgrAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(bgrAInfo, pixelsB, "PixelMap_RGBA_to_bgrA"); - - auto BGRAInfo = bgrAInfo.makeAlphaType(AlphaType::Unpremultiplied); - result = RGBAMap.readPixels(BGRAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_RGBA_to_BGRA"); - - PixelMap BGRAMap(BGRAInfo, pixelsB); - - result = BGRAMap.readPixels(BGRAInfo, pixelsA); - EXPECT_TRUE(result); - CHECK_PIXELS(BGRAInfo, pixelsA, "PixelMap_BGRA_to_BGRA"); - - result = BGRAMap.readPixels(RGBAInfo, pixelsA); - EXPECT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixelsA, "PixelMap_BGRA_to_RGBA"); - - result = BGRAMap.readPixels(rgbAInfo, pixelsA); - EXPECT_TRUE(result); - CHECK_PIXELS(rgbAInfo, pixelsA, "PixelMap_BGRA_to_rgbA"); - - PixelMap rgbAMap(rgbAInfo, pixelsA); - - result = rgbAMap.readPixels(RGBAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_rgbA_to_RGBA"); - - result = rgbAMap.readPixels(BGRAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_rgbA_to_BGRA"); - - result = rgbAMap.readPixels(bgrAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(bgrAInfo, pixelsB, "PixelMap_rgbA_to_bgrA"); - - auto A8Info = ImageInfo::Make(width, height, ColorType::ALPHA_8, AlphaType::Unpremultiplied); - EXPECT_EQ(A8Info.alphaType(), AlphaType::Premultiplied); - auto alphaByteSize = A8Info.byteSize(); - auto pixelsC = new uint8_t[alphaByteSize]; - - result = rgbAMap.readPixels(A8Info, pixelsC); - EXPECT_TRUE(result); - CHECK_PIXELS(A8Info, pixelsC, "PixelMap_rgbA_to_alpha"); - - PixelMap A8Map(A8Info, pixelsC); - - result = A8Map.readPixels(rgbAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(rgbAInfo, pixelsB, "PixelMap_alpha_to_rgbA"); - - result = A8Map.readPixels(BGRAInfo, pixelsB); - EXPECT_TRUE(result); - CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_alpha_to_BGRA"); - - delete[] pixelsA; - delete[] pixelsB; - delete[] pixelsC; - PAGTestEnvironment::DumpJson["PixelMapTest"] = outputJson; + auto image = Image::MakeFrom("../resources/apitest/test_timestretch.png"); + EXPECT_TRUE(image != nullptr); + auto width = image->width(); + auto height = image->height(); + auto RGBAInfo = ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Unpremultiplied); + auto byteSize = RGBAInfo.byteSize(); + auto pixelsA = new uint8_t[byteSize]; + auto pixelsB = new uint8_t[byteSize]; + auto result = image->readPixels(RGBAInfo, pixelsA); + EXPECT_TRUE(result); + + json compareJson = PAGTestEnvironment::CompareJson["PixelMapTest"]; + json outputJson = {}; + + PixelMap RGBAMap(RGBAInfo, pixelsA); + CHECK_PIXELS(RGBAInfo, pixelsA, "PixelMap_RGBA_Original"); + + result = RGBAMap.readPixels(RGBAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_RGBA_to_RGBA"); + + memset(pixelsB, 0, RGBAInfo.byteSize()); + result = RGBAMap.readPixels(RGBAInfo, pixelsB, 100, 100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_RGBA_to_RGBA_100_100"); + + auto RGBARectInfo = ImageInfo::Make(500, 500, ColorType::RGBA_8888, AlphaType::Premultiplied); + memset(pixelsB, 0, RGBARectInfo.byteSize()); + result = RGBAMap.readPixels(RGBARectInfo, pixelsB, -100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixelsB, "PixelMap_RGBA_to_RGBA_-100_-100"); + + memset(pixelsB, 0, RGBARectInfo.byteSize()); + result = RGBAMap.readPixels(RGBARectInfo, pixelsB, 100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixelsB, "PixelMap_RGBA_to_RGBA_100_-100"); + + auto rgbAInfo = RGBAInfo.makeAlphaType(AlphaType::Premultiplied); + result = RGBAMap.readPixels(rgbAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(rgbAInfo, pixelsB, "PixelMap_RGBA_to_rgbA"); + + auto bgrAInfo = rgbAInfo.makeColorType(ColorType::BGRA_8888); + result = RGBAMap.readPixels(bgrAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(bgrAInfo, pixelsB, "PixelMap_RGBA_to_bgrA"); + + auto BGRAInfo = bgrAInfo.makeAlphaType(AlphaType::Unpremultiplied); + result = RGBAMap.readPixels(BGRAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_RGBA_to_BGRA"); + + PixelMap BGRAMap(BGRAInfo, pixelsB); + + result = BGRAMap.readPixels(BGRAInfo, pixelsA); + EXPECT_TRUE(result); + CHECK_PIXELS(BGRAInfo, pixelsA, "PixelMap_BGRA_to_BGRA"); + + result = BGRAMap.readPixels(RGBAInfo, pixelsA); + EXPECT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixelsA, "PixelMap_BGRA_to_RGBA"); + + result = BGRAMap.readPixels(rgbAInfo, pixelsA); + EXPECT_TRUE(result); + CHECK_PIXELS(rgbAInfo, pixelsA, "PixelMap_BGRA_to_rgbA"); + + PixelMap rgbAMap(rgbAInfo, pixelsA); + + result = rgbAMap.readPixels(RGBAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixelsB, "PixelMap_rgbA_to_RGBA"); + + result = rgbAMap.readPixels(BGRAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_rgbA_to_BGRA"); + + result = rgbAMap.readPixels(bgrAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(bgrAInfo, pixelsB, "PixelMap_rgbA_to_bgrA"); + + auto A8Info = ImageInfo::Make(width, height, ColorType::ALPHA_8, AlphaType::Unpremultiplied); + EXPECT_EQ(A8Info.alphaType(), AlphaType::Premultiplied); + auto alphaByteSize = A8Info.byteSize(); + auto pixelsC = new uint8_t[alphaByteSize]; + + result = rgbAMap.readPixels(A8Info, pixelsC); + EXPECT_TRUE(result); + CHECK_PIXELS(A8Info, pixelsC, "PixelMap_rgbA_to_alpha"); + + PixelMap A8Map(A8Info, pixelsC); + + result = A8Map.readPixels(rgbAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(rgbAInfo, pixelsB, "PixelMap_alpha_to_rgbA"); + + result = A8Map.readPixels(BGRAInfo, pixelsB); + EXPECT_TRUE(result); + CHECK_PIXELS(BGRAInfo, pixelsB, "PixelMap_alpha_to_BGRA"); + + delete[] pixelsA; + delete[] pixelsB; + delete[] pixelsC; + PAGTestEnvironment::DumpJson["PixelMapTest"] = outputJson; } /** * 用例描述: 像素格式转换相关功能测试-SurfaceReadPixels */ PAG_TEST(ReadPixelsTest, TestSurfaceReadPixels) { - auto image = Image::MakeFrom("../resources/apitest/test_timestretch.png"); - ASSERT_TRUE(image != nullptr); - Bitmap bitmap = {}; - auto result = bitmap.allocPixels(image->width(), image->height()); - ASSERT_TRUE(result); - auto pixels = bitmap.lockPixels(); - result = image->readPixels(bitmap.info(), pixels); - bitmap.unlockPixels(); - ASSERT_TRUE(result); - - auto device = NativeGLDevice::Make(); - auto context = device->lockContext(); - ASSERT_TRUE(context != nullptr); - auto texture = bitmap.makeTexture(context); - ASSERT_TRUE(texture != nullptr); - auto surface = Surface::Make(context, bitmap.width(), bitmap.height()); - ASSERT_TRUE(surface != nullptr); - auto canvas = surface->getCanvas(); - canvas->drawTexture(texture.get()); - - BitmapLock lock(bitmap); - auto width = bitmap.width(); - auto height = bitmap.height(); - pixels = lock.pixels(); - json outputJson = {}; - json compareJson = PAGTestEnvironment::CompareJson["SurfaceReadPixelsTest"]; - - auto RGBAInfo = ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Premultiplied); - result = surface->readPixels(RGBAInfo, pixels); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixels, "Surface_rgbA_to_rgbA"); - - auto BGRAInfo = ImageInfo::Make(width, height, ColorType::BGRA_8888, AlphaType::Premultiplied); - result = surface->readPixels(BGRAInfo, pixels); - ASSERT_TRUE(result); - CHECK_PIXELS(BGRAInfo, pixels, "Surface_rgbA_to_bgrA"); - - memset(pixels, 0, RGBAInfo.byteSize()); - result = surface->readPixels(RGBAInfo, pixels, 100, 100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixels, "Surface_rgbA_to_rgbA_100_100"); - - auto RGBARectInfo = ImageInfo::Make(500, 500, ColorType::RGBA_8888, AlphaType::Premultiplied); - memset(pixels, 0, RGBARectInfo.byteSize()); - result = surface->readPixels(RGBARectInfo, pixels, -100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixels, "Surface_rgbA_to_rgbA_-100_-100"); - - memset(pixels, 0, RGBARectInfo.byteSize()); - result = surface->readPixels(RGBARectInfo, pixels, 100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixels, "Surface_rgbA_to_rgbA_100_-100"); - - surface = Surface::Make(context, bitmap.width(), bitmap.height(), true); - ASSERT_TRUE(surface != nullptr); - canvas = surface->getCanvas(); - canvas->drawTexture(texture.get()); - - auto A8Info = ImageInfo::Make(width, height, ColorType::ALPHA_8, AlphaType::Premultiplied); - result = surface->readPixels(A8Info, pixels); - ASSERT_TRUE(result); - CHECK_PIXELS(A8Info, pixels, "Surface_alpha_to_alpha"); - - result = surface->readPixels(RGBAInfo, pixels); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixels, "Surface_alpha_to_rgba"); - - auto AlphaRectInfo = ImageInfo::Make(500, 500, ColorType::ALPHA_8, AlphaType::Premultiplied); - memset(pixels, 0, AlphaRectInfo.byteSize()); - result = surface->readPixels(AlphaRectInfo, pixels, 100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(AlphaRectInfo, pixels, "Surface_alpha_to_alpha_100_-100"); - - auto gl = GLContext::Unwrap(context); - GLTextureInfo textureInfo = {}; - result = CreateTexture(gl, width, height, &textureInfo); - ASSERT_TRUE(result); - auto backendTexture = BackendTexture(textureInfo, width, height); - surface = Surface::MakeFrom(context, backendTexture, ImageOrigin::BottomLeft); - ASSERT_TRUE(surface != nullptr); - canvas = surface->getCanvas(); - canvas->clear(); - canvas->drawTexture(texture.get()); - - result = surface->readPixels(RGBAInfo, pixels); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixels, "Surface_BL_rgbA_to_rgbA"); - - memset(pixels, 0, RGBAInfo.byteSize()); - result = surface->readPixels(RGBAInfo, pixels, 100, 100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBAInfo, pixels, "Surface_BL_rgbA_to_rgbA_100_100"); - - memset(pixels, 0, RGBARectInfo.byteSize()); - result = surface->readPixels(RGBARectInfo, pixels, -100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixels, "Surface_BL_rgbA_to_rgbA_-100_-100"); - - memset(pixels, 0, RGBARectInfo.byteSize()); - result = surface->readPixels(RGBARectInfo, pixels, 100, -100); - ASSERT_TRUE(result); - CHECK_PIXELS(RGBARectInfo, pixels, "Surface_BL_rgbA_to_rgbA_100_-100"); - - gl->deleteTextures(1, &textureInfo.id); - device->unlock(); - PAGTestEnvironment::DumpJson["SurfaceReadPixelsTest"] = outputJson; + auto image = Image::MakeFrom("../resources/apitest/test_timestretch.png"); + ASSERT_TRUE(image != nullptr); + Bitmap bitmap = {}; + auto result = bitmap.allocPixels(image->width(), image->height()); + ASSERT_TRUE(result); + auto pixels = bitmap.lockPixels(); + result = image->readPixels(bitmap.info(), pixels); + bitmap.unlockPixels(); + ASSERT_TRUE(result); + + auto device = NativeGLDevice::Make(); + auto context = device->lockContext(); + ASSERT_TRUE(context != nullptr); + auto texture = bitmap.makeTexture(context); + ASSERT_TRUE(texture != nullptr); + auto surface = Surface::Make(context, bitmap.width(), bitmap.height()); + ASSERT_TRUE(surface != nullptr); + auto canvas = surface->getCanvas(); + canvas->drawTexture(texture.get()); + + BitmapLock lock(bitmap); + auto width = bitmap.width(); + auto height = bitmap.height(); + pixels = lock.pixels(); + json outputJson = {}; + json compareJson = PAGTestEnvironment::CompareJson["SurfaceReadPixelsTest"]; + + auto RGBAInfo = ImageInfo::Make(width, height, ColorType::RGBA_8888, AlphaType::Premultiplied); + result = surface->readPixels(RGBAInfo, pixels); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixels, "Surface_rgbA_to_rgbA"); + + auto BGRAInfo = ImageInfo::Make(width, height, ColorType::BGRA_8888, AlphaType::Premultiplied); + result = surface->readPixels(BGRAInfo, pixels); + ASSERT_TRUE(result); + CHECK_PIXELS(BGRAInfo, pixels, "Surface_rgbA_to_bgrA"); + + memset(pixels, 0, RGBAInfo.byteSize()); + result = surface->readPixels(RGBAInfo, pixels, 100, 100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixels, "Surface_rgbA_to_rgbA_100_100"); + + auto RGBARectInfo = ImageInfo::Make(500, 500, ColorType::RGBA_8888, AlphaType::Premultiplied); + memset(pixels, 0, RGBARectInfo.byteSize()); + result = surface->readPixels(RGBARectInfo, pixels, -100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixels, "Surface_rgbA_to_rgbA_-100_-100"); + + memset(pixels, 0, RGBARectInfo.byteSize()); + result = surface->readPixels(RGBARectInfo, pixels, 100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixels, "Surface_rgbA_to_rgbA_100_-100"); + + surface = Surface::Make(context, bitmap.width(), bitmap.height(), true); + ASSERT_TRUE(surface != nullptr); + canvas = surface->getCanvas(); + canvas->drawTexture(texture.get()); + + auto A8Info = ImageInfo::Make(width, height, ColorType::ALPHA_8, AlphaType::Premultiplied); + result = surface->readPixels(A8Info, pixels); + ASSERT_TRUE(result); + CHECK_PIXELS(A8Info, pixels, "Surface_alpha_to_alpha"); + + result = surface->readPixels(RGBAInfo, pixels); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixels, "Surface_alpha_to_rgba"); + + auto AlphaRectInfo = ImageInfo::Make(500, 500, ColorType::ALPHA_8, AlphaType::Premultiplied); + memset(pixels, 0, AlphaRectInfo.byteSize()); + result = surface->readPixels(AlphaRectInfo, pixels, 100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(AlphaRectInfo, pixels, "Surface_alpha_to_alpha_100_-100"); + + auto gl = GLContext::Unwrap(context); + GLTextureInfo textureInfo = {}; + result = CreateTexture(gl, width, height, &textureInfo); + ASSERT_TRUE(result); + auto backendTexture = BackendTexture(textureInfo, width, height); + surface = Surface::MakeFrom(context, backendTexture, ImageOrigin::BottomLeft); + ASSERT_TRUE(surface != nullptr); + canvas = surface->getCanvas(); + canvas->clear(); + canvas->drawTexture(texture.get()); + + result = surface->readPixels(RGBAInfo, pixels); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixels, "Surface_BL_rgbA_to_rgbA"); + + memset(pixels, 0, RGBAInfo.byteSize()); + result = surface->readPixels(RGBAInfo, pixels, 100, 100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBAInfo, pixels, "Surface_BL_rgbA_to_rgbA_100_100"); + + memset(pixels, 0, RGBARectInfo.byteSize()); + result = surface->readPixels(RGBARectInfo, pixels, -100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixels, "Surface_BL_rgbA_to_rgbA_-100_-100"); + + memset(pixels, 0, RGBARectInfo.byteSize()); + result = surface->readPixels(RGBARectInfo, pixels, 100, -100); + ASSERT_TRUE(result); + CHECK_PIXELS(RGBARectInfo, pixels, "Surface_BL_rgbA_to_rgbA_100_-100"); + + gl->deleteTextures(1, &textureInfo.id); + device->unlock(); + PAGTestEnvironment::DumpJson["SurfaceReadPixelsTest"] = outputJson; } /** * 用例描述: Webp解码测试 */ PAG_TEST(ReadPixelsTest, WebpCodec) { - auto image = Image::MakeFrom("../resources/apitest/imageReplacement.webp"); - ASSERT_TRUE(image != nullptr); - ASSERT_EQ(image->width(), 110); - ASSERT_EQ(image->height(), 110); - ASSERT_EQ(static_cast(image->orientation()), static_cast(Orientation::TopLeft)); - auto rowBytes = image->width() * 4; - auto pixels = new (std::nothrow) uint8_t[rowBytes * image->height()]; - ASSERT_TRUE(pixels); - auto info = ImageInfo::Make(110, 110, ColorType::RGBA_8888, AlphaType::Premultiplied); - bool res = image->readPixels(info, pixels); - ASSERT_TRUE(res); - PixelMap pixelMap(info, pixels); - Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); - Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::WEBP, 100); - Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::JPEG, 100); - delete[] pixels; + auto image = Image::MakeFrom("../resources/apitest/imageReplacement.webp"); + ASSERT_TRUE(image != nullptr); + ASSERT_EQ(image->width(), 110); + ASSERT_EQ(image->height(), 110); + ASSERT_EQ(static_cast(image->orientation()), static_cast(Orientation::TopLeft)); + auto rowBytes = image->width() * 4; + auto pixels = new (std::nothrow) uint8_t[rowBytes * image->height()]; + ASSERT_TRUE(pixels); + auto info = ImageInfo::Make(110, 110, ColorType::RGBA_8888, AlphaType::Premultiplied); + bool res = image->readPixels(info, pixels); + ASSERT_TRUE(res); + PixelMap pixelMap(info, pixels); + Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); + Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::WEBP, 100); + Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::JPEG, 100); + delete[] pixels; } /** * 用例描述: Jpeg解码测试 */ PAG_TEST(ReadPixelsTest, JpegCodec) { - auto image = Image::MakeFrom("../resources/apitest/rotation.jpg"); - ASSERT_TRUE(image != nullptr); - ASSERT_EQ(image->width(), 4032); - ASSERT_EQ(image->height(), 3024); - ASSERT_EQ(static_cast(image->orientation()), static_cast(Orientation::RightTop)); - ColorType outputColorType = ColorType::RGBA_8888; - auto pixels = new (std::nothrow) - uint8_t[image->height() * image->width() * ImageInfo::GetBytesPerPixel(outputColorType)]; - ASSERT_TRUE(pixels); - auto info = ImageInfo::Make(4032, 3024, outputColorType, AlphaType::Premultiplied); - bool res = image->readPixels(info, pixels); - PixelMap pixelMap(info, pixels); - - auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::WEBP, 20); - if (bytes) { - std::ofstream out("../test/out/tet.webp"); - out.write(reinterpret_cast(bytes->data()), bytes->size()); - out.close(); - } - delete[] pixels; - ASSERT_TRUE(res); + auto image = Image::MakeFrom("../resources/apitest/rotation.jpg"); + ASSERT_TRUE(image != nullptr); + ASSERT_EQ(image->width(), 4032); + ASSERT_EQ(image->height(), 3024); + ASSERT_EQ(static_cast(image->orientation()), static_cast(Orientation::RightTop)); + ColorType outputColorType = ColorType::RGBA_8888; + auto pixels = new (std::nothrow) + uint8_t[image->height() * image->width() * ImageInfo::GetBytesPerPixel(outputColorType)]; + ASSERT_TRUE(pixels); + auto info = ImageInfo::Make(4032, 3024, outputColorType, AlphaType::Premultiplied); + bool res = image->readPixels(info, pixels); + PixelMap pixelMap(info, pixels); + + auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::WEBP, 20); + if (bytes) { + std::ofstream out("../test/out/tet.webp"); + out.write(reinterpret_cast(bytes->data()), bytes->size()); + out.close(); + } + delete[] pixels; + ASSERT_TRUE(res); } } // namespace pag diff --git a/test/TestUtils.cpp b/test/TestUtils.cpp index ffc112b4e8..d7d38bcbf9 100644 --- a/test/TestUtils.cpp +++ b/test/TestUtils.cpp @@ -21,19 +21,19 @@ #include void GetAllPAGFiles(std::string path, std::vector& files) { - struct dirent* dirp; - DIR* dir = opendir(path.c_str()); - std::string p; + struct dirent* dirp; + DIR* dir = opendir(path.c_str()); + std::string p; - while ((dirp = readdir(dir)) != nullptr) { - if (dirp->d_type == DT_REG) { - std::string str(dirp->d_name); - std::string::size_type idx = str.find(".pag"); - if (idx != std::string::npos) { - files.push_back(p.assign(path).append("/").append(dirp->d_name)); - } + while ((dirp = readdir(dir)) != nullptr) { + if (dirp->d_type == DT_REG) { + std::string str(dirp->d_name); + std::string::size_type idx = str.find(".pag"); + if (idx != std::string::npos) { + files.push_back(p.assign(path).append("/").append(dirp->d_name)); + } + } } - } - closedir(dir); + closedir(dir); } \ No newline at end of file diff --git a/test/framework/PAGCpuTest.cpp b/test/framework/PAGCpuTest.cpp index 2b7a1320cb..c450da105e 100644 --- a/test/framework/PAGCpuTest.cpp +++ b/test/framework/PAGCpuTest.cpp @@ -46,29 +46,29 @@ void PAGCpuTest::TearDown() { } void PAGCpuTest::PagSetUp(std::string pagPath) { - TestPAGFile = PAGFile::Load(pagPath); - ASSERT_NE(TestPAGFile, nullptr) << "pag path is:" << GetPagPath() << std::endl; - TestPAGSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); - TestPAGPlayer = std::make_shared(); - TestPAGPlayer->setSurface(TestPAGSurface); - TestPAGPlayer->setComposition(TestPAGFile); + TestPAGFile = PAGFile::Load(pagPath); + ASSERT_NE(TestPAGFile, nullptr) << "pag path is:" << GetPagPath() << std::endl; + TestPAGSurface = PAGSurface::MakeOffscreen(TestPAGFile->width(), TestPAGFile->height()); + TestPAGPlayer = std::make_shared(); + TestPAGPlayer->setSurface(TestPAGSurface); + TestPAGPlayer->setComposition(TestPAGFile); } void PAGCpuTest::PagTearDown() { - TestPAGFile = nullptr; - TestPAGSurface = nullptr; - TestPAGPlayer = nullptr; + TestPAGFile = nullptr; + TestPAGSurface = nullptr; + TestPAGPlayer = nullptr; } std::string PAGCpuTest::GetPagPath() { - return DEFAULT_PAG_PATH; + return DEFAULT_PAG_PATH; } std::string PAGCpuTest::getMd5FromSnap() { - if (TestPAGSurface == nullptr) { - return ""; - } - return DumpMD5(TestPAGSurface); + if (TestPAGSurface == nullptr) { + return ""; + } + return DumpMD5(TestPAGSurface); } } // namespace pag diff --git a/test/framework/PAGCpuTest.h b/test/framework/PAGCpuTest.h index 1cc48547b7..2659e7161f 100644 --- a/test/framework/PAGCpuTest.h +++ b/test/framework/PAGCpuTest.h @@ -26,47 +26,47 @@ namespace pag { class PAGCpuTest : public testing::Test { - public: - PAGCpuTest(); +public: + PAGCpuTest(); - ~PAGCpuTest() override; + ~PAGCpuTest() override; - /** - * Sets up the test suite. - */ - static void SetUpTestSuite(); + /** + * Sets up the test suite. + */ + static void SetUpTestSuite(); - /** - * Sets down the test suite. - */ - static void TearDownTestSuite(); + /** + * Sets down the test suite. + */ + static void TearDownTestSuite(); - /** - * Sets up the test case. - */ - void SetUp() override; + /** + * Sets up the test case. + */ + void SetUp() override; - /** - * Sets down the test case. - */ - void TearDown() override; + /** + * Sets down the test case. + */ + void TearDown() override; - static void PagSetUp(std::string pagPath); + static void PagSetUp(std::string pagPath); - static void PagTearDown(); + static void PagTearDown(); - static std::string GetPagPath(); + static std::string GetPagPath(); - static std::shared_ptr TestPAGFile; + static std::shared_ptr TestPAGFile; - static std::shared_ptr TestPAGSurface; + static std::shared_ptr TestPAGSurface; - static std::shared_ptr TestPAGPlayer; + static std::shared_ptr TestPAGPlayer; - static std::string getMd5FromSnap(); + static std::string getMd5FromSnap(); - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(PAGCpuTest); +private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(PAGCpuTest); }; } // namespace pag diff --git a/test/framework/PAGTestEnvironment.cpp b/test/framework/PAGTestEnvironment.cpp index 19deb75454..73f9b37ac2 100644 --- a/test/framework/PAGTestEnvironment.cpp +++ b/test/framework/PAGTestEnvironment.cpp @@ -30,36 +30,37 @@ PAGTestEnvironment::~PAGTestEnvironment() { } static void RegisterSoftwareDecoder() { - auto factory = ffavc::DecoderFactory::GetHandle(); - pag::PAGVideoDecoder::RegisterSoftwareDecoderFactory( - reinterpret_cast(factory)); + auto factory = ffavc::DecoderFactory::GetHandle(); + pag::PAGVideoDecoder::RegisterSoftwareDecoderFactory( + reinterpret_cast(factory)); } void PAGTestEnvironment::SetUp() { - std::vector fontPaths = {"../resources/font/NotoSansSC-Regular.otf", - "../resources/font/NotoColorEmoji.ttf"}; - std::vector ttcIndices = {0, 0}; - pag::PAGFont::SetFallbackFontPaths(fontPaths, ttcIndices); - RegisterSoftwareDecoder(); + std::vector fontPaths = {"../resources/font/NotoSansSC-Regular.otf", + "../resources/font/NotoColorEmoji.ttf" + }; + std::vector ttcIndices = {0, 0}; + pag::PAGFont::SetFallbackFontPaths(fontPaths, ttcIndices); + RegisterSoftwareDecoder(); #ifdef COMPARE_JSON_PATH - std::ifstream inputFile(COMPARE_JSON_PATH); - if (!inputFile) { - std::cout << "open " << COMPARE_JSON_PATH << " fail"; - CompareJson = {}; - } else { - inputFile >> CompareJson; - } + std::ifstream inputFile(COMPARE_JSON_PATH); + if (!inputFile) { + std::cout << "open " << COMPARE_JSON_PATH << " fail"; + CompareJson = {}; + } else { + inputFile >> CompareJson; + } #endif } void PAGTestEnvironment::TearDown() { - if (DumpJson == nullptr) { - return; - } - std::ofstream outFile(DUMP_JSON_PATH); - outFile << std::setw(4) << DumpJson << std::endl; - outFile.close(); + if (DumpJson == nullptr) { + return; + } + std::ofstream outFile(DUMP_JSON_PATH); + outFile << std::setw(4) << DumpJson << std::endl; + outFile.close(); } } // namespace pag diff --git a/test/framework/PAGTestEnvironment.h b/test/framework/PAGTestEnvironment.h index 90a6714341..805f3ae383 100644 --- a/test/framework/PAGTestEnvironment.h +++ b/test/framework/PAGTestEnvironment.h @@ -24,15 +24,15 @@ namespace pag { class PAGTestEnvironment : public testing::Environment { - public: - static nlohmann::json DumpJson; - static nlohmann::json CompareJson; - static std::mutex GlobalLocker; +public: + static nlohmann::json DumpJson; + static nlohmann::json CompareJson; + static std::mutex GlobalLocker; - virtual ~PAGTestEnvironment() override; + virtual ~PAGTestEnvironment() override; - virtual void SetUp() override; + virtual void SetUp() override; - virtual void TearDown() override; + virtual void TearDown() override; }; } // namespace pag \ No newline at end of file diff --git a/test/framework/pagtest_main.cpp b/test/framework/pagtest_main.cpp index 69dab7cdee..cc98808cb6 100644 --- a/test/framework/pagtest_main.cpp +++ b/test/framework/pagtest_main.cpp @@ -19,8 +19,8 @@ #include "PAGTestEnvironment.h" int main(int argc, char** argv) { - printf("Running main() from %s\n", __FILE__); - AddGlobalTestEnvironment(new pag::PAGTestEnvironment()); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + printf("Running main() from %s\n", __FILE__); + AddGlobalTestEnvironment(new pag::PAGTestEnvironment()); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/test/framework/utils/PAGTestUtils.cpp b/test/framework/utils/PAGTestUtils.cpp index a896360799..7879da4b26 100644 --- a/test/framework/utils/PAGTestUtils.cpp +++ b/test/framework/utils/PAGTestUtils.cpp @@ -23,124 +23,124 @@ namespace pag { std::string DumpMD5(const void* bytes, size_t size) { - unsigned char digest[CC_MD5_DIGEST_LENGTH] = {0}; + unsigned char digest[CC_MD5_DIGEST_LENGTH] = {0}; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - CC_MD5(bytes, size, digest); + CC_MD5(bytes, size, digest); #pragma clang diagnostic pop - char buffer[32]; - char* position = buffer; - for (unsigned char i : digest) { - sprintf(position, "%02x", i); - position += 2; - } - return {buffer, 32}; + char buffer[32]; + char* position = buffer; + for (unsigned char i : digest) { + sprintf(position, "%02x", i); + position += 2; + } + return {buffer, 32}; } std::string DumpMD5(const Bitmap& bitmap) { - if (bitmap.isEmpty()) { - return ""; - } - BitmapLock lock(bitmap); - return DumpMD5(lock.pixels(), bitmap.byteSize()); + if (bitmap.isEmpty()) { + return ""; + } + BitmapLock lock(bitmap); + return DumpMD5(lock.pixels(), bitmap.byteSize()); } std::string DumpMD5(std::shared_ptr pixelBuffer) { - if (pixelBuffer == nullptr) { - return ""; - } - auto pixels = pixelBuffer->lockPixels(); - auto result = DumpMD5(pixels, pixelBuffer->byteSize()); - pixelBuffer->unlockPixels(); - return result; + if (pixelBuffer == nullptr) { + return ""; + } + auto pixels = pixelBuffer->lockPixels(); + auto result = DumpMD5(pixels, pixelBuffer->byteSize()); + pixelBuffer->unlockPixels(); + return result; } std::string DumpMD5(const PixelMap& pixelMap) { - if (pixelMap.isEmpty()) { - return ""; - } - return DumpMD5(pixelMap.pixels(), pixelMap.byteSize()); + if (pixelMap.isEmpty()) { + return ""; + } + return DumpMD5(pixelMap.pixels(), pixelMap.byteSize()); } Bitmap MakeSnapshot(std::shared_ptr pagSurface) { - Bitmap bitmap = {}; - if (!bitmap.allocPixels(pagSurface->width(), pagSurface->height())) { + Bitmap bitmap = {}; + if (!bitmap.allocPixels(pagSurface->width(), pagSurface->height())) { + return bitmap; + } + BitmapLock lock(bitmap); + auto result = pagSurface->readPixels(bitmap.colorType(), bitmap.alphaType(), lock.pixels(), + bitmap.rowBytes()); + if (!result) { + bitmap.reset(); + } return bitmap; - } - BitmapLock lock(bitmap); - auto result = pagSurface->readPixels(bitmap.colorType(), bitmap.alphaType(), lock.pixels(), - bitmap.rowBytes()); - if (!result) { - bitmap.reset(); - } - return bitmap; } std::string DumpMD5(std::shared_ptr pagSurface) { - auto image = MakeSnapshot(pagSurface); - return DumpMD5(image); + auto image = MakeSnapshot(pagSurface); + return DumpMD5(image); } static void TraceImage(const PixelMap& pixelMap, const std::string& tag) { - std::string path = tag; - if (path.empty()) { - path = "TraceImage.png"; - } else if (path.rfind(".png") != path.size() - 4 && path.rfind(".PNG") != path.size() - 4) { - path += ".png"; - } - auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); - if (bytes) { - std::ofstream out(path); - out.write(reinterpret_cast(bytes->data()), bytes->size()); - out.close(); - } + std::string path = tag; + if (path.empty()) { + path = "TraceImage.png"; + } else if (path.rfind(".png") != path.size() - 4 && path.rfind(".PNG") != path.size() - 4) { + path += ".png"; + } + auto bytes = Image::Encode(pixelMap.info(), pixelMap.pixels(), EncodedFormat::PNG, 100); + if (bytes) { + std::ofstream out(path); + out.write(reinterpret_cast(bytes->data()), bytes->size()); + out.close(); + } } void TraceIf(const Bitmap& bitmap, const std::string& path, bool condition) { - BitmapLock lock(bitmap); - PixelMap pixelMap(bitmap.info(), lock.pixels()); - TraceIf(pixelMap, path, condition); + BitmapLock lock(bitmap); + PixelMap pixelMap(bitmap.info(), lock.pixels()); + TraceIf(pixelMap, path, condition); } void TraceIf(std::shared_ptr pixelBuffer, const std::string& path, bool condition) { - auto pixels = pixelBuffer->lockPixels(); - PixelMap pixelMap(pixelBuffer->info(), pixels); - TraceIf(pixelMap, path, condition); - pixelBuffer->unlockPixels(); + auto pixels = pixelBuffer->lockPixels(); + PixelMap pixelMap(pixelBuffer->info(), pixels); + TraceIf(pixelMap, path, condition); + pixelBuffer->unlockPixels(); } void TraceIf(const PixelMap& pixelMap, const std::string& path, bool condition) { // condition = true; // 忽略条件输出所有图片。 - if (condition) { - TraceImage(pixelMap, path); - } + if (condition) { + TraceImage(pixelMap, path); + } } void TraceIf(std::shared_ptr pagSurface, const std::string& path, bool condition) { - auto image = MakeSnapshot(pagSurface); - TraceIf(image, path, condition); + auto image = MakeSnapshot(pagSurface); + TraceIf(image, path, condition); } std::shared_ptr GetLayer(std::shared_ptr root, LayerType type, int& targetIndex) { - if (root == nullptr) return nullptr; - if (type == LayerType::PreCompose) { - if (targetIndex == 0) { - return root; + if (root == nullptr) return nullptr; + if (type == LayerType::PreCompose) { + if (targetIndex == 0) { + return root; + } + targetIndex--; } - targetIndex--; - } - for (int i = 0; i < root->numChildren(); i++) { - auto layer = root->getLayerAt(i); - if (layer->layerType() == type) { - if (targetIndex == 0) { - return layer; - } - targetIndex--; - } else if (layer->layerType() == LayerType::PreCompose) { - return GetLayer(std::static_pointer_cast(layer), type, targetIndex); + for (int i = 0; i < root->numChildren(); i++) { + auto layer = root->getLayerAt(i); + if (layer->layerType() == type) { + if (targetIndex == 0) { + return layer; + } + targetIndex--; + } else if (layer->layerType() == LayerType::PreCompose) { + return GetLayer(std::static_pointer_cast(layer), type, targetIndex); + } } - } - return nullptr; + return nullptr; } } // namespace pag \ No newline at end of file diff --git a/test/framework/utils/Semaphore.cpp b/test/framework/utils/Semaphore.cpp index 64ad418998..580dfb9110 100644 --- a/test/framework/utils/Semaphore.cpp +++ b/test/framework/utils/Semaphore.cpp @@ -20,16 +20,16 @@ namespace pag { void Semaphore::signal() { - std::lock_guard autoLock(locker); - count++; - condition.notify_one(); + std::lock_guard autoLock(locker); + count++; + condition.notify_one(); } void Semaphore::wait() { - std::unique_lock autoLock(locker); - if (count <= 0) { - condition.wait(autoLock); - } - count--; + std::unique_lock autoLock(locker); + if (count <= 0) { + condition.wait(autoLock); + } + count--; } } // namespace pag \ No newline at end of file diff --git a/test/framework/utils/Semaphore.h b/test/framework/utils/Semaphore.h index c78bdd8d2b..27450bd025 100644 --- a/test/framework/utils/Semaphore.h +++ b/test/framework/utils/Semaphore.h @@ -22,17 +22,17 @@ namespace pag { class Semaphore { - public: - explicit Semaphore(int count) : count(count) { - } +public: + explicit Semaphore(int count) : count(count) { + } - void signal(); + void signal(); - void wait(); + void wait(); - private: - int count = 0; - std::mutex locker = {}; - std::condition_variable condition = {}; +private: + int count = 0; + std::mutex locker = {}; + std::condition_variable condition = {}; }; } // namespace pag \ No newline at end of file