mirror of
				https://github.com/RetroDECK/ES-DE.git
				synced 2025-04-10 19:15:13 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			115 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "plutovg-private.h"
 | |
| 
 | |
| #include <math.h>
 | |
| 
 | |
| plutovg_dash_t* plutovg_dash_create(double offset, const double* data, int size)
 | |
| {
 | |
|     if(data==NULL || size==0)
 | |
|         return NULL;
 | |
| 
 | |
|     plutovg_dash_t* dash = malloc(sizeof(plutovg_dash_t));
 | |
|     dash->offset = offset;
 | |
|     dash->data = malloc((size_t)size * sizeof(double));
 | |
|     dash->size = size;
 | |
|     memcpy(dash->data, data, (size_t)size * sizeof(double));
 | |
|     return dash;
 | |
| }
 | |
| 
 | |
| plutovg_dash_t* plutovg_dash_clone(const plutovg_dash_t* dash)
 | |
| {
 | |
|     if(dash==NULL)
 | |
|         return NULL;
 | |
| 
 | |
|     return plutovg_dash_create(dash->offset, dash->data, dash->size);
 | |
| }
 | |
| 
 | |
| void plutovg_dash_destroy(plutovg_dash_t* dash)
 | |
| {
 | |
|     if(dash==NULL)
 | |
|         return;
 | |
| 
 | |
|     free(dash->data);
 | |
|     free(dash);
 | |
| }
 | |
| 
 | |
| plutovg_path_t* plutovg_dash_path(const plutovg_dash_t* dash, const plutovg_path_t* path)
 | |
| {
 | |
|     if(dash->data==NULL || dash->size==0)
 | |
|         return plutovg_path_clone(path);
 | |
| 
 | |
|     int toggle = 1;
 | |
|     int offset = 0;
 | |
|     double phase = dash->offset;
 | |
|     while(phase >= dash->data[offset])
 | |
|     {
 | |
|         toggle = !toggle;
 | |
|         phase -= dash->data[offset];
 | |
|         offset += 1;
 | |
|         if(offset == dash->size) offset = 0;
 | |
|     }
 | |
| 
 | |
|     plutovg_path_t* flat = plutovg_path_clone_flat(path);
 | |
|     plutovg_path_t* result = plutovg_path_create();
 | |
|     plutovg_array_ensure(result->elements, flat->elements.size);
 | |
|     plutovg_array_ensure(result->points, flat->points.size);
 | |
| 
 | |
|     plutovg_path_element_t* elements = flat->elements.data;
 | |
|     plutovg_path_element_t* end = elements + flat->elements.size;
 | |
|     plutovg_point_t* points = flat->points.data;
 | |
|     while(elements < end)
 | |
|     {
 | |
|         int itoggle = toggle;
 | |
|         int ioffset = offset;
 | |
|         double iphase = phase;
 | |
| 
 | |
|         double x0 = points->x;
 | |
|         double y0 = points->y;
 | |
| 
 | |
|         if(itoggle)
 | |
|             plutovg_path_move_to(result, x0, y0);
 | |
| 
 | |
|         ++elements;
 | |
|         ++points;
 | |
| 
 | |
|         while(elements < end && *elements==plutovg_path_element_line_to)
 | |
|         {
 | |
|             double dx = points->x - x0;
 | |
|             double dy = points->y - y0;
 | |
|             double dist0 = sqrt(dx*dx + dy*dy);
 | |
|             double dist1 = 0;
 | |
| 
 | |
|             while(dist0 - dist1 > dash->data[ioffset] - iphase)
 | |
|             {
 | |
|                 dist1 += dash->data[ioffset] - iphase;
 | |
|                 double a = dist1 / dist0;
 | |
|                 double x = x0 + a * dx;
 | |
|                 double y = y0 + a * dy;
 | |
| 
 | |
|                 if(itoggle)
 | |
|                     plutovg_path_line_to(result, x, y);
 | |
|                 else
 | |
|                     plutovg_path_move_to(result, x, y);
 | |
| 
 | |
|                 itoggle = !itoggle;
 | |
|                 iphase = 0;
 | |
|                 ioffset += 1;
 | |
|                 if(ioffset == dash->size) ioffset = 0;
 | |
|             }
 | |
| 
 | |
|             iphase += dist0 - dist1;
 | |
| 
 | |
|             x0 = points->x;
 | |
|             y0 = points->y;
 | |
| 
 | |
|             if(itoggle)
 | |
|                 plutovg_path_line_to(result, x0, y0);
 | |
| 
 | |
|             ++elements;
 | |
|             ++points;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     plutovg_path_destroy(flat);
 | |
|     return result;
 | |
| }
 | 
