void SvgTreeBuilder::line(clan::DomElement &e) { float x0 = (float)SvgAttributeReader::single_length(e, "x0"); float y0 = (float)SvgAttributeReader::single_length(e, "y0"); float x1 = (float)SvgAttributeReader::single_length(e, "x1"); float y1 = (float)SvgAttributeReader::single_length(e, "y1"); auto path = clan::Path::line(x0, y0, x1, y1); render_path(path, e); }
void SvgTreeBuilder::circle(clan::DomElement &e) { float cx = (float)SvgAttributeReader::single_length(e, "cx"); float cy = (float)SvgAttributeReader::single_length(e, "cy"); float r = (float)SvgAttributeReader::single_length(e, "r"); if (r != 0.0f) { auto path = clan::Path::circle(cx, cy, r); render_path(path, e); } }
void SvgTreeBuilder::ellipse(clan::DomElement &e) { float cx = (float)SvgAttributeReader::single_length(e, "cx"); float cy = (float)SvgAttributeReader::single_length(e, "cy"); float rx = (float)SvgAttributeReader::single_length(e, "rx"); float ry = (float)SvgAttributeReader::single_length(e, "ry"); if (rx != 0.0f && ry != 0.0f) { auto path = clan::Path::ellipse(cx, cy, rx, ry); render_path(path, e); } }
void SvgTreeBuilder::rect(clan::DomElement &e) { float x = (float)SvgAttributeReader::single_length(e, "x"); float y = (float)SvgAttributeReader::single_length(e, "y"); float width = (float)SvgAttributeReader::single_length(e, "width"); float height = (float)SvgAttributeReader::single_length(e, "height"); if (width != 0.0f && height != 0.0f) { auto path = clan::Path::rect(x, y, width, height); render_path(path, e); } }
void raster_raster(Raster *raster) { StyleMachine _m, *m = &_m; PathElement *e; memset(m, 0, sizeof(*m)); memset(raster->buffer, 255, raster->size[0]*raster->size[1]*4); for (e=raster->renderlist.first; e; e=e->next) { if (e->type == PATH_PATH) { render_path(m, raster, (Path*)e); } else { render_segment(raster, (PathSegment*)e); } } }
bool SkDrawPathCommand::render(SkCanvas* canvas) const { render_path(canvas, fPath); return true; }
void SvgTreeBuilder::path(clan::DomElement &e) { SvgAttributeReader data(e, "d"); clan::Path path; try { double last_x = 0.0; double last_y = 0.0; double last_cp_x = 0.0f; double last_cp_y = 0.0f; while (!data.is_end()) { char command = data.get_path_command(); bool absolute = (command >= 'A' && command <= 'Z'); if (command != 'Z' && command != 'z' && !data.is_number()) data.parse_error("unexpected path data"); switch (command) { case 'M': // Move to (abs) case 'm': // Move to (rel) { double mx = data.get_sequence_number(); double my = data.get_sequence_number(); if (!absolute) { mx += last_x; my += last_y; } path.move_to((float)mx, (float)my); last_x = mx; last_y = my; last_cp_x = last_x; last_cp_y = last_y; while (data.is_sequence_number()) { double lx = data.get_sequence_number(); double ly = data.get_sequence_number(); if (!absolute) { lx += last_x; ly += last_y; } path.line_to((float)lx, (float)ly); last_x = lx; last_y = ly; last_cp_x = last_x; last_cp_y = last_y; } break; } case 'Z': // Close path case 'z': path.close(); break; case 'L': // Line to (abs) case 'l': // Line to (rel) do { double x = data.get_sequence_number(); double y = data.get_sequence_number(); if (!absolute) { x += last_x; y += last_y; } path.line_to((float)x, (float)y); last_x = x; last_y = y; last_cp_x = last_x; last_cp_y = last_y; } while (data.is_sequence_number()); break; case 'H': // Horizontal line to (abs) case 'h': // Horizontal line to (rel) do { double x = data.get_sequence_number(); if (!absolute) x += last_x; path.line_to((float)x, (float)last_y); last_x = x; last_cp_x = last_x; } while (data.is_sequence_number()); break; case 'V': // Vertical line to (abs) case 'v': // Vertical line to (rel) do { double y = data.get_number(); if (!absolute) y += last_y; path.line_to((float)last_x, (float)y); last_y = y; last_cp_y = last_y; } while (data.is_sequence_number()); break; case 'C': // Cubic curve to (abs) case 'c': // Cubic curve to (rel) do { double x1 = data.get_sequence_number(); double y1 = data.get_sequence_number(); double x2 = data.get_sequence_number(); double y2 = data.get_sequence_number(); double x = data.get_sequence_number(); double y = data.get_sequence_number(); if (!absolute) { x1 += last_x; y1 += last_y; x2 += last_x; y2 += last_y; x += last_x; y += last_y; } path.bezier_to(clan::Pointf((float)x1, (float)y1), clan::Pointf((float)x2, (float)y2), clan::Pointf((float)x, (float)y)); last_x = x; last_y = y; last_cp_x = x2; last_cp_y = y2; } while (data.is_sequence_number()); break; case 'S': // Shorthand/smooth cubic curve to (abs) case 's': // Shorthand/smooth cubic curve to (rel) do { double x2 = data.get_sequence_number(); double y2 = data.get_sequence_number(); double x = data.get_sequence_number(); double y = data.get_sequence_number(); if (!absolute) { x2 += last_x; y2 += last_y; x += last_x; y += last_y; } double x1 = last_cp_x + x - last_x; double y1 = last_cp_y + y - last_y; path.bezier_to(clan::Pointf((float)x1, (float)y1), clan::Pointf((float)x2, (float)y2), clan::Pointf((float)x, (float)y)); last_x = x; last_y = y; last_cp_x = x2; last_cp_y = y2; } while (data.is_sequence_number()); break; case 'Q': // Quadratic curve to (abs) case 'q': // Quadratic curve to (rel) do { double x1 = data.get_sequence_number(); double y1 = data.get_sequence_number(); double x = data.get_sequence_number(); double y = data.get_sequence_number(); if (!absolute) { x1 += last_x; y1 += last_y; x += last_x; y += last_y; } path.bezier_to(clan::Pointf((float)x1, (float)y1), clan::Pointf((float)x, (float)y)); last_x = x; last_y = y; last_cp_x = x1; last_cp_y = y1; } while (data.is_sequence_number()); break; case 'T': // Shorthand/smooth quadratic curve to (abs) case 't': // Shorthand/smooth quadratic curve to (rel) do { double x = data.get_sequence_number(); double y = data.get_sequence_number(); if (!absolute) { x += last_x; y += last_y; } double x1 = last_cp_x + x - last_x; double y1 = last_cp_y + y - last_y; path.bezier_to(clan::Pointf((float)x1, (float)y1), clan::Pointf((float)x, (float)y)); last_x = x; last_y = y; last_cp_x = x1; last_cp_y = y1; } while (data.is_sequence_number()); break; case 'A': // Elliptical arc (abs) case 'a': // Elliptical arc (rel) do { double rx = data.get_sequence_number(); double ry = data.get_sequence_number(); double x_axis_rotate = data.get_sequence_number(); double y_axis_rotate = data.get_sequence_number(); double large_arc_flag = data.get_sequence_number(); double sweep_flag = data.get_sequence_number(); double x = data.get_sequence_number(); double y = data.get_sequence_number(); last_x = x; last_y = y; last_cp_x = last_x; last_cp_y = last_y; } while (data.is_sequence_number()); break; default: break; } } } catch (clan::Exception &) { } render_path(path, e); }
void render_scene(state_t state) { srand(time(NULL)); int TILE_W; if(state.gpu_enabled == true) { TILE_W = TILE_W_GPU; } else { TILE_W = TILE_W_CPU; } image_t img = {.w=state.image_w, .h=state.image_h, .pixels=(vec3*)malloc(sizeof(vec3)*state.image_w*state.image_h)}; pthread_t t0; if(display) { cur_state = state; int result; result = pthread_create(&t0, NULL, run_display_update, NULL); qr_assert(result==0, "root", "Pthread creation failed: %d",result); while(window_closed) { sleep(0); } } //render image //only AO is supported as of now int tiles_x = (int)(img.w/(float)TILE_W+0.99999); int tiles_y = (int)(img.h/(float)TILE_W+0.99999); num_tiles_done = 0; num_tiles_total = tiles_x*tiles_y; render_done = false; if(state.gpu_enabled == false) { pthread_t t1; int result; result = pthread_create(&t1, NULL, run_status_update, NULL); qr_assert(result==0, "root", "Pthread creation failed: %d",result); #pragma omp parallel for schedule(dynamic) for(int i=0; i<tiles_x*tiles_y; i++) { int x = i/tiles_x; int y = i%tiles_x; int tile_w,tile_h; if(x == tiles_x-1) { tile_w = img.w-TILE_W*(tiles_x-1); } else { tile_w = TILE_W; } if(y == tiles_y-1) { tile_h = img.h-TILE_W*(tiles_y-1); } else { tile_h = TILE_W; } image_t tile = {.w=tile_w, .h=tile_h, .pixels=(vec3*)malloc(sizeof(vec3)*tile_w*tile_h)}; memset(tile.pixels, 0, sizeof(vec3)*tile_w*tile_h); if(state.renderer == RENDERER_AO) { render_ao(state, tile, display, x*TILE_W, y*TILE_W); } else if(state.renderer == RENDERER_PATH) { render_path(state, tile, display, x*TILE_W, y*TILE_W); } else { ERROR("root", "Unknown renderer ID: %d",state.renderer); } //copy tile to image for(int xx=0; xx<tile_w; xx++) { for(int yy=0; yy<tile_h; yy++) { img.pixels[(xx+x*tile_w)+(yy+y*tile_h)*img.w] = tile.pixels[xx+yy*tile_w]; } } #pragma omp atomic num_tiles_done++; } render_done = true; pthread_join(t1, NULL); } else { switch(state.renderer) { case RENDERER_AO: init_ao_gpu(state, TILE_W, TILE_W); break; case RENDERER_PATH: init_path_gpu(state, TILE_W, TILE_W); break; }; for(int i=0; i<tiles_x*tiles_y; i++) { int x = i/tiles_x; int y = i%tiles_x; int tile_w,tile_h; if(x == tiles_x-1) { tile_w = img.w-TILE_W*(tiles_x-1); } else { tile_w = TILE_W; } if(y == tiles_y-1) { tile_h = img.h-TILE_W*(tiles_y-1); } else { tile_h = TILE_W; } image_t tile = {.w=tile_w, .h=tile_h, .pixels=(vec3*)malloc(sizeof(vec3)*tile_w*tile_h)}; memset(tile.pixels, 0, sizeof(vec3)*tile_w*tile_h); if(state.renderer == RENDERER_AO) { render_ao_gpu(state, tile, display, x*TILE_W, y*TILE_W); } else if(state.renderer == RENDERER_PATH) { render_path_gpu(state, tile,display, x*TILE_W, y*TILE_W); } else { ERROR("root", "Unknown renderer ID: %d",state.renderer); } //copy tile to image for(int xx=0; xx<tile_w; xx++) { for(int yy=0; yy<tile_h; yy++) { img.pixels[(xx+x*tile_w)+(yy+y*tile_h)*img.w] = tile.pixels[xx+yy*tile_w]; } } printf("%c[2K\rTiles: %d/%d",27,i,num_tiles_total); } switch(state.renderer) { case RENDERER_AO: exit_ao_gpu(); break; case RENDERER_PATH: exit_path_gpu(); }; render_done = true; } printf("Done rendering\n"); if(display) { display_image(img,0,0); } //write image write_image(state.outfile, img); if(display) { pthread_join(t0, NULL); } free(img.pixels); } int main(int argc, char** argv) { char* ofile_override = NULL; char** input_files = (char**)malloc(sizeof(char*)); int n_input_files = 0; //parse command line arguments { int i = 1; while(i<argc) { if(argv[i][0] == '-') { //it is a flag switch(argv[i][1]) { case 'o': //override all output files i++; ofile_override = argv[i]; break; case 'd': //no graphics i++; display = false; break; default: ERROR("root", "Invalid flag: %s", argv[i]); } } else { //input file input_files[n_input_files] = argv[i]; n_input_files++; input_files = (char**)realloc(input_files, sizeof(char*)*n_input_files); } i++; } } //parse input files for(int i=0; i<n_input_files; i++) { printf("Parsing file %s\n", input_files[i]); state_t state = parse_file(input_files[i]); if(ofile_override) state.outfile = ofile_override; #ifdef DEBUG //print summary printf("Summary:\n output file: %s\n spp: %d\n width: %d\n height: %d\n primitives: %d\n", state.outfile, state.spp, state.image_w, state.image_h, state.n_primitives); #else printf("primitives: %d\nwidth: %d\nheight: %d\n", state.n_primitives, state.image_w, state.image_h); #endif //construct bvh construct_bvh(&state); //render scene render_scene(state); } return 0; }