Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复部分函数使用 ege_transform_matrix 参数做变换时崩溃的问题 #234

Merged
merged 5 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 44 additions & 37 deletions src/egegapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@
#include "ege_head.h"
#include "ege_common.h"
#include "ege_extension.h"
#include "gdi_conv.h"

#include <cmath>
#include <cstdarg>
#include <cstdio>


#include <stdio.h>

namespace ege
{

Expand Down Expand Up @@ -2388,8 +2387,10 @@ void ege_path_widen(ege_path* path, float lineWidth, const ege_transform_matrix*
if (path != NULL) {
Gdiplus::GraphicsPath* graphicsPath = (Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
Gdiplus::Pen pen(Gdiplus::Color(), lineWidth);
graphicsPath->Widen(&pen, (const Gdiplus::Matrix*)matrix, flatness);
const Gdiplus::Pen pen(Gdiplus::Color(), lineWidth);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->Widen(&pen, mat, flatness);
delete mat;
}
}
}
Expand All @@ -2403,8 +2404,11 @@ void ege_path_flatten(ege_path* path, const ege_transform_matrix* matrix, float
{
if (path != NULL) {
Gdiplus::GraphicsPath* graphicsPath = (Gdiplus::GraphicsPath*)path->data();

if (graphicsPath != NULL) {
graphicsPath->Flatten((const Gdiplus::Matrix*)matrix, flatness);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->Flatten(mat, flatness);
delete mat;
}
}
}
Expand All @@ -2421,8 +2425,11 @@ void ege_path_warp(ege_path* path, const ege_point* points, int count, const ege
if ((path != NULL) && (points != NULL) && (rect != NULL) && ((count == 3) || (count == 4))) {
Gdiplus::GraphicsPath* graphicsPath = (Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
graphicsPath->Warp((const Gdiplus::PointF*)points, count, *(const Gdiplus::RectF*)rect,
(const Gdiplus::Matrix*)matrix, Gdiplus::WarpModePerspective, flatness);
const Gdiplus::PointF* p = (const Gdiplus::PointF*)points;
const Gdiplus::RectF r(rect->x, rect->y, rect->w, rect->h);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->Warp(p, count, r, mat, Gdiplus::WarpModePerspective, flatness);
delete mat;
}
}
}
Expand All @@ -2437,7 +2444,9 @@ void ege_path_outline(ege_path* path, const ege_transform_matrix* matrix, float
if (path != NULL) {
Gdiplus::GraphicsPath* graphicsPath = (Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
graphicsPath->Outline((const Gdiplus::Matrix*)matrix, flatness);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->Outline(mat, flatness);
delete mat;
}
}
}
Expand Down Expand Up @@ -2523,7 +2532,9 @@ ege_rect ege_path_getbounds(const ege_path* path, const ege_transform_matrix* ma
if (path != NULL) {
const Gdiplus::GraphicsPath* graphicsPath = (const Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
graphicsPath->GetBounds((Gdiplus::RectF*)&bounds, (const Gdiplus::Matrix*)matrix);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->GetBounds((Gdiplus::RectF*)&bounds, mat);
delete mat;
}
}

Expand All @@ -2537,10 +2548,13 @@ ege_rect ege_path_getbounds(const ege_path* path, const ege_transform_matrix* ma
const Gdiplus::GraphicsPath* graphicsPath = (const Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
PIMAGE img = CONVERT_IMAGE_CONST((PIMAGE)pimg);
graphicsPath->GetBounds((Gdiplus::RectF*)&bounds, (const Gdiplus::Matrix*)matrix, img->getPen());
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->GetBounds((Gdiplus::RectF*)&bounds, mat, img->getPen());
delete mat;
CONVERT_IMAGE_END
}
}

return bounds;
}

Expand Down Expand Up @@ -2589,10 +2603,12 @@ unsigned char* ege_path_getpathtypes(const ege_path* path, unsigned char* types)

void ege_path_transform(ege_path* path, const ege_transform_matrix *matrix)
{
if (path != NULL) {
if ((path != NULL) && (matrix != NULL)) {
Gdiplus::GraphicsPath* graphicsPath = (Gdiplus::GraphicsPath*)path->data();
if (graphicsPath != NULL) {
graphicsPath->Transform((const Gdiplus::Matrix*)matrix);
const Gdiplus::Matrix* mat = matrixConvert(matrix);
graphicsPath->Transform(mat);
delete mat;
}
}
}
Expand Down Expand Up @@ -2826,12 +2842,12 @@ void EGEAPI ege_transform_reset(PIMAGE pimg)
void EGEAPI ege_get_transform(ege_transform_matrix* matrix, PIMAGE pimg)
{
PIMAGE img = CONVERT_IMAGE(pimg);
if (img) {
if (img && matrix) {
Gdiplus::Graphics* graphics = img->getGraphics();
Gdiplus::Matrix m;
Gdiplus::Matrix mat;
Gdiplus::REAL elements[6];
graphics->GetTransform(&m);
m.GetElements(elements);
graphics->GetTransform(&mat);
mat.GetElements(elements);
matrix->m11 = elements[0];
matrix->m12 = elements[1];
matrix->m21 = elements[2];
Expand All @@ -2845,40 +2861,31 @@ void EGEAPI ege_get_transform(ege_transform_matrix* matrix, PIMAGE pimg)
void EGEAPI ege_set_transform(const ege_transform_matrix* matrix, PIMAGE pimg)
{
PIMAGE img = CONVERT_IMAGE(pimg);
if (img) {
if (img && matrix) {
Gdiplus::Graphics* graphics = img->getGraphics();
Gdiplus::Matrix m(matrix->m11, matrix->m12, matrix->m21, matrix->m22, matrix->m31, matrix->m32);
graphics->SetTransform(&m);
const Gdiplus::Matrix mat(matrix->m11, matrix->m12, matrix->m21, matrix->m22, matrix->m31, matrix->m32);
graphics->SetTransform(&mat);
}
CONVERT_IMAGE_END;
}

ege_point EGEAPI ege_transform_calc(ege_point p, PIMAGE pimg) { return ege_transform_calc(p.x, p.y, pimg); }
ege_point EGEAPI ege_transform_calc(ege_point p, PIMAGE pimg)
{
return ege_transform_calc(p.x, p.y, pimg);
}

ege_point EGEAPI ege_transform_calc(float x, float y, PIMAGE pimg)
{
PIMAGE img = CONVERT_IMAGE(pimg);
ege_point p;
ege_point point = {0.0f, 0.0f};
if (img) {
Gdiplus::Graphics* graphics = img->getGraphics();
Gdiplus::Matrix m;
Gdiplus::REAL elements[6], m11, m12, m21, m22, m31, m32;
graphics->GetTransform(&m);
m.GetElements(elements);
m11 = elements[0];
m12 = elements[1];
m21 = elements[2];
m22 = elements[3];
m31 = elements[4];
m32 = elements[5];
p.x = x * m11 + y * m21 + m31;
p.y = x * m12 + y * m22 + m32;
} else {
p.x = 0;
p.y = 0;
Gdiplus::Matrix matrix;
graphics->GetTransform(&matrix);
matrix.TransformPoints((Gdiplus::PointF*)&point, 1);
}
CONVERT_IMAGE_END;
return p;
return point;
}

#endif // EGEGDIPLUS
Expand Down
24 changes: 24 additions & 0 deletions src/gdi_conv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "ege_head.h"
#include "gdi_conv.h"

namespace ege
{

/**
* 将ege_transform_matrix 转换为 Gdiplus::Matrix
* matrix 参数不为 NULL 时返回 Matrix 对象指针,否则返回 NULL
*/
Gdiplus::Matrix* matrixConvert(const ege_transform_matrix* matrix)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种设计方式不太好吧, 返回一个需要delete的对象, 直接传入引用, 然后 return 对象是不是更好, 也不用处理 NULL 的情况了。

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

就算是按 C 风格的设计模式, 应该也是把输出一起传入才对? 比如 itoa 啥的...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这种设计方式不太好吧, 返回一个需要delete的对象, 直接传入引用, 然后 return 对象是不是更好, 也不用处理 NULL 的情况了。

@wysaid OK,可以改成引用的方式。当时这么设计主要是考虑两点:

  • Gdiplus::Matrix 禁止赋值,返回不了对象,只能以指针的形式返回。
  • GDI+ 涉及变换的函数都对空指针特殊处理,不进行变换。如果改成对象,就需要改为传入单位矩阵,需要并且有额外计算。实际使用时代码处理也会更复杂一些。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

因为是 C 形式的接口,ege_transform_matrix 是指针参数,所以空指针判断操作避免不了

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

主要还是要保持的 c++ 版本比较低, 不然你可以用 std::optional 之类的 来防止 new, 也能很好利用 RVO/NRVO 啥的....
要封装成函数确实麻烦... 如果封装成宏定义, 倒是简单很多...
我看你还单独为这个函数单独弄了个头文件....

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

主要还是要保持的 c++ 版本比较低, 不然你可以用 std::optional 之类的 来防止 new, 也能很好利用 RVO/NRVO 啥的.... 要封装成函数确实麻烦... 如果封装成宏定义, 倒是简单很多... 我看你还单独为这个函数单独弄了个头文件....

@wysaid 因为后续可能还会加不少类似的类型转换,就单独建一个源文件了,转换操作统一放里面

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wysaid 改好了,看看这样可以不

{
if (matrix != NULL) {
return new Gdiplus::Matrix(
matrix->m11, matrix->m12,
matrix->m21, matrix->m22,
matrix->m31, matrix->m32
);
}

return NULL;
}

}
9 changes: 9 additions & 0 deletions src/gdi_conv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "ege_head.h"

namespace ege
{
/* 矩阵类型转换*/
Gdiplus::Matrix* matrixConvert(const ege_transform_matrix* matrix);
}
Loading