[Bf-blender-cvs] [705d8e70e72] temp-gpencil-bezier-v2: Fix memory issues and crashes.
Falk David
noreply at git.blender.org
Fri Feb 12 01:18:22 CET 2021
Commit: 705d8e70e72cff480fa788a2cb5680c7890e4993
Author: Falk David
Date: Fri Feb 12 01:15:28 2021 +0100
Branches: temp-gpencil-bezier-v2
https://developer.blender.org/rB705d8e70e72cff480fa788a2cb5680c7890e4993
Fix memory issues and crashes.
===================================================================
M source/blender/blenkernel/intern/gpencil_curve.c
===================================================================
diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c
index 0c5eaabe8c9..f6159549bd3 100644
--- a/source/blender/blenkernel/intern/gpencil_curve.c
+++ b/source/blender/blenkernel/intern/gpencil_curve.c
@@ -604,25 +604,55 @@ static void gpencil_free_curve_segment(tGPCurveSegment *tcs)
return;
}
- if (tcs->point_array != NULL) {
+ if (tcs->point_array != NULL && tcs->point_array_len > 0) {
MEM_freeN(tcs->point_array);
}
- if (tcs->curve_points != NULL) {
+ if (tcs->curve_points != NULL && tcs->cubic_array_len > 0) {
MEM_freeN(tcs->curve_points);
}
- if (tcs->cubic_array != NULL) {
- MEM_freeN(tcs->cubic_array);
+ if (tcs->cubic_array != NULL && tcs->cubic_array_len > 0) {
+ free(tcs->cubic_array);
}
- if (tcs->cubic_orig_index != NULL) {
- MEM_freeN(tcs->cubic_orig_index);
+ if (tcs->cubic_orig_index != NULL && tcs->cubic_array_len > 0) {
+ free(tcs->cubic_orig_index);
}
- if (tcs->corners_index_array != NULL) {
- MEM_freeN(tcs->corners_index_array);
+ if (tcs->corners_index_array != NULL && tcs->corners_index_len > 0) {
+ free(tcs->corners_index_array);
}
-
+
MEM_freeN(tcs);
}
+static bool gpencil_is_segment_tagged(bGPDstroke *gps, const uint32_t cpt_start)
+{
+ bGPDcurve *gpc = gps->editcurve;
+ const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC);
+ const uint32_t cpt_end = (cpt_start + 1) % gpc->tot_curve_points;
+
+ const uint32_t start_pt_idx = gpc->curve_points[cpt_start].point_index;
+ const uint32_t end_pt_idx = gpc->curve_points[cpt_end].point_index;
+
+ if (!is_cyclic && (cpt_start == gpc->tot_curve_points - 1)) {
+ return false;
+ }
+
+ /* Check endpoints of segment frist. */
+ if ((gps->points[start_pt_idx].flag & GP_SPOINT_TAG) ||
+ (gps->points[end_pt_idx].flag & GP_SPOINT_TAG)) {
+ return true;
+ }
+
+ /* Iterate over all stroke points in between and check if any point is tagged. */
+ for (int i = start_pt_idx + 1; i < end_pt_idx - 1; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ if ((pt->flag & GP_SPOINT_TAG)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static int gpencil_count_tagged_curve_segments(bGPDstroke *gps)
{
bGPDcurve *gpc = gps->editcurve;
@@ -631,43 +661,25 @@ static int gpencil_count_tagged_curve_segments(bGPDstroke *gps)
return (gps->points[0].flag & GP_SPOINT_TAG) ? 1 : 0;
}
- /* Iterate over segments. */
- const int tot_segments = gpc->tot_curve_points - 1;
+ /* Iterate over points and check if segment is tagged. */
int count = 0;
- for (int i = 0; i < tot_segments; i++) {
- int start_idx = gpc->curve_points[i].point_index;
- int end_idx = gpc->curve_points[i + 1].point_index;
- for (int j = start_idx; j <= end_idx; j++) {
- bGPDspoint *pt = &gps->points[j];
- if ((pt->flag & GP_SPOINT_TAG)) {
- count++;
- break;
- }
- }
- }
-
- /* Handle closing segment */
- if (gps->flag & GP_STROKE_CYCLIC) {
- int start_idx = gpc->curve_points[gpc->tot_curve_points - 1].point_index;
- int end_idx = gps->totpoints - 1;
-
- if ((gps->points[0].flag) & GP_SPOINT_TAG) {
+ for (int i = 0; i < gpc->tot_curve_points; i++) {
+ if (gpencil_is_segment_tagged(gps, i)) {
count++;
}
- else {
- for (int j = start_idx; j <= end_idx; j++) {
- bGPDspoint *pt = &gps->points[j];
- if ((pt->flag & GP_SPOINT_TAG)) {
- count++;
- break;
- }
- }
- }
}
return count;
}
+static void gpencil_clear_point_tag(bGPDstroke *gps)
+{
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ pt->flag &= ~GP_SPOINT_TAG;
+ }
+}
+
static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps)
{
BLI_assert(gps->totpoints < 3);
@@ -742,13 +754,14 @@ static bGPDcurve *gpencil_stroke_editcurve_generate_edgecases(bGPDstroke *gps)
return NULL;
}
-static tGPCurveSegment *gpencil_generate_curve_segment(bGPDstroke *gps,
+/* Helper: Generates a tGPCurveSegment using the stroke points in gps from the start index up to
+ * the end index. */
+static tGPCurveSegment *gpencil_fit_curve_to_points_ex(bGPDstroke *gps,
const float diag_length,
const float error_threshold,
const float corner_angle,
const uint32_t start_idx,
- const uint32_t end_idx,
- const uint32_t offset)
+ const uint32_t end_idx)
{
const uint32_t length = end_idx - start_idx + 1;
@@ -771,11 +784,12 @@ static tGPCurveSegment *gpencil_generate_curve_segment(bGPDstroke *gps,
mul_v4_v4fl(cfpt->color, pt->vert_color, 1.0f / diag_length);
}
+ int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY;
int r = curve_fit_cubic_to_points_refit_fl(tcs->point_array,
length,
CURVE_FIT_POINT_DIM,
error_threshold,
- CURVE_FIT_CALC_HIGH_QUALIY,
+ calc_flag,
NULL,
0,
corner_angle,
@@ -811,12 +825,20 @@ static tGPCurveSegment *gpencil_generate_curve_segment(bGPDstroke *gps,
bezt->h1 = HD_ALIGN;
bezt->h2 = HD_ALIGN;
- cpt->point_index = tcs->cubic_orig_index[i] + offset;
+ /* Make sure to add the start index. */
+ cpt->point_index = tcs->cubic_orig_index[i] + start_idx;
}
- /* Set handle type to HD_FREE for corner handles. */
- if (tcs->corners_index_len > 0 && tcs->corners_index_array != NULL) {
- for (int i = 0; i < tcs->corners_index_len; i++) {
+ /* Set handle type to HD_FREE for corner handles. Ignore first and last. */
+ if (tcs->corners_index_array != NULL) {
+ uint i_start = 0, i_end = tcs->corners_index_len;
+
+ if ((tcs->corners_index_len >= 2) && (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) {
+ i_start += 1;
+ i_end -= 1;
+ }
+
+ for (uint i = i_start; i < i_end; i++) {
bGPDcurve_point *cpt = &tcs->curve_points[tcs->corners_index_array[i]];
BezTriple *bezt = &cpt->bezt;
bezt->h1 = HD_FREE;
@@ -959,7 +981,8 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_regenerate(bGPDstroke *gps,
* longer treat it as a control point). Therefor the only option is to find */
bGPDcurve *gpc = gps->editcurve;
- const int tot_segments = gpc->tot_curve_points - 1;
+ const int num_segments = gpc->tot_curve_points - 1;
+ printf("num_segments: %d\n", num_segments);
float diag_length = len_v3v3(gps->boundbox_min, gps->boundbox_max);
ListBase curve_segments = {NULL, NULL};
@@ -968,99 +991,63 @@ bGPDcurve *BKE_gpencil_stroke_editcurve_regenerate(bGPDstroke *gps,
* that is not tagged. */
tGPCurveSegment *tcs;
- int new_tot_curve_points = 0, pt_offset = 0;
- for (int i = 0; i < tot_segments; i++) {
+ int j = 0, new_num_segments = 0;
+ for (int i = 0; i < num_segments; i = j) {
+ int island_length = 1;
int start_idx = gpc->curve_points[i].point_index;
- bGPDspoint *start_pt = &gps->points[start_idx];
-
- bool regen = false;
- if ((start_pt->flag & GP_SPOINT_TAG)) {
- regen = true;
- }
+ bool is_tagged = gpencil_is_segment_tagged(gps, i);
- /* Find end point. */
- int end_idx = start_idx;
- for (int j = i + 1; j < gpc->tot_curve_points; j++, i++) {
+ /* Find the end of this island (tagged or un-tagged). */
+ int end_idx;
+ bGPDspoint *end_pt;
+ for (j = i + 1; j < gpc->tot_curve_points; j++, island_length++) {
end_idx = gpc->curve_points[j].point_index;
- bGPDspoint *pt = &gps->points[end_idx];
- if ((pt->flag & GP_SPOINT_TAG) == 0) {
+ end_pt = &gps->points[end_idx];
+ if (!(is_tagged && (end_pt->flag & GP_SPOINT_TAG)) &&
+ (gpencil_is_segment_tagged(gps, j) != is_tagged)) {
break;
}
- regen = true;
}
- if (!regen) {
- /* Check if there are marked points between the control points. If there are, the segment
- * must be regenerated. */
- for (int k = start_idx + 1; k < end_idx; k++) {
- bGPDspoint *pt = &gps->points[k];
- if ((pt->flag & GP_SPOINT_TAG)) {
- regen = true;
- tcs = gpencil_generate_curve_segment(
- gps, diag_length, error_threshold, corner_angle, start_idx, end_idx, pt_offset);
- break;
- }
- }
- }
- else {
+ printf("i: %d, j: %d, length: %d\n", i, j, island_length);
+
+ if (is_tagged) {
/* Regenerate this segment. */
- regen = true;
- tcs = gpencil_generate_curve_segment(
- gps, diag_length, error_threshold, corner_angle, start_idx, end_idx, pt_offset);
+ tcs = gpencil_fit_curve_to_points_ex(
+ gps, diag_length, error_threshold, corner_angle, start_idx, end_idx);
}
-
- if (!regen) {
- int start_cidx = i;
- /* Find end point. This time for curve points that have not moved. */
- int end_cidx = start_cidx;
- for (int j = start_cidx + 1; j < gpc->tot_curve_points; j++, i++) {
- bGPDspoint *pt = &gps->points[gpc->curve_points[j].point_index];
- if (pt->flag & GP_SPOINT_TAG) {
- break;
- }
- end_cidx = j;
- }
-
+ else {
+ /* Save this segment. */
tcs = MEM_callocN(sizeof(tGPCurveSegment), __func__);
- tcs->cubic_array_len = end_cidx - start_cidx + 1;
- tcs->point_array_len = gpc->curve_points[end_cidx].point_index -
- gpc->curve_points[start_cidx].point_index + 1;
+ tcs->cubic_array_len = island_length;
+ tcs->point_array_len = end_idx - start_idx + 1;
tcs->curve_points = MEM_callocN(sizeof(bGPDcurve_point) * tcs->cubic_array_len, __func__
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list