SUMOReal MSCFModel_Kerner::_v(const MSVehicle* const veh, SUMOReal speed, SUMOReal vfree, SUMOReal gap, SUMOReal predSpeed) const { if (predSpeed == 0 && gap < 0.01) { return 0; } // !!! in the following, the prior step is not considered!!! SUMOReal G = MAX2((SUMOReal) 0, (SUMOReal)(SPEED2DIST(myK * speed) + myPhi / myAccel * speed * (speed - predSpeed))); SUMOReal vcond = gap > G ? speed + ACCEL2SPEED(myAccel) : speed + MAX2(ACCEL2SPEED(-myDecel), MIN2(ACCEL2SPEED(myAccel), predSpeed - speed)); SUMOReal vsafe = (SUMOReal)(-1. * myTauDecel + sqrt(myTauDecel * myTauDecel + (predSpeed * predSpeed) + (2. * myDecel * gap))); VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables(); SUMOReal va = MAX2((SUMOReal) 0, MIN3(vfree, vsafe, vcond)) + vars->rand; SUMOReal v = MAX2((SUMOReal) 0, MIN4(vfree, va, speed + ACCEL2SPEED(myAccel), vsafe)); return v; }
void gimp_display_shell_rotate_untransform_bounds (GimpDisplayShell *shell, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *nx1, gdouble *ny1, gdouble *nx2, gdouble *ny2) { gdouble tx1, ty1; gdouble tx2, ty2; gdouble tx3, ty3; gdouble tx4, ty4; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); tx1 = x1; ty1 = y1; tx2 = x1; ty2 = y2; tx3 = x2; ty3 = y1; tx4 = x2; ty4 = y2; cairo_matrix_transform_point (shell->rotate_untransform, &tx1, &ty1); cairo_matrix_transform_point (shell->rotate_untransform, &tx2, &ty2); cairo_matrix_transform_point (shell->rotate_untransform, &tx3, &ty3); cairo_matrix_transform_point (shell->rotate_untransform, &tx4, &ty4); *nx1 = MIN4 (tx1, tx2, tx3, tx4); *ny1 = MIN4 (ty1, ty2, ty3, ty4); *nx2 = MAX4 (tx1, tx2, tx3, tx4); *ny2 = MAX4 (ty1, ty2, ty3, ty4); }
static void get_bounding_box (GtkWidget *widget, GdkRectangle *bounds) { GtkAllocation allocation; GdkWindow *window; gint x, y; gint w, h; gint x1, y1; gint x2, y2; gint x3, y3; gint x4, y4; window = gtk_widget_get_parent_window (widget); if (window == NULL) window = gtk_widget_get_window (widget); gtk_widget_get_allocation (widget, &allocation); x = allocation.x; y = allocation.y; w = allocation.width; h = allocation.height; gdk_window_get_root_coords (window, x, y, &x1, &y1); gdk_window_get_root_coords (window, x + w, y, &x2, &y2); gdk_window_get_root_coords (window, x, y + h, &x3, &y3); gdk_window_get_root_coords (window, x + w, y + h, &x4, &y4); #define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d)) #define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d)) bounds->x = floor (MIN4 (x1, x2, x3, x4)); bounds->y = floor (MIN4 (y1, y2, y3, y4)); bounds->width = ceil (MAX4 (x1, x2, x3, x4)) - bounds->x; bounds->height = ceil (MAX4 (y1, y2, y3, y4)) - bounds->y; }
SUMOReal MSCFModel_KraussOrig1::moveHelper(MSVehicle * const veh, const MSLane * const lane, SUMOReal vPos) const throw() { SUMOReal oldV = veh->getSpeed(); // save old v for optional acceleration computation SUMOReal vSafe = MIN2(vPos, veh->processNextStop(vPos)); // process stops // we need the acceleration for emission computation; // in this case, we neglect dawdling, nonetheless, using // vSafe does not incorporate speed reduction due to interaction // on lane changing veh->setPreDawdleAcceleration(SPEED2ACCEL(vSafe-oldV)); // SUMOReal vNext = dawdle(MIN3(lane->getMaxSpeed(), maxNextSpeed(oldV), vSafe)); vNext = veh->getLaneChangeModel().patchSpeed( MAX2((SUMOReal) 0, oldV-(SUMOReal)ACCEL2SPEED(myDecel)), //!!! reverify vNext, MIN3(vSafe, veh->getLane().getMaxSpeed(), maxNextSpeed(oldV)),//vaccel(myState.mySpeed, myLane->maxSpeed())), vSafe); return MIN4(vNext, vSafe, veh->getLane().getMaxSpeed(), maxNextSpeed(oldV)); }
int compute_dequeue_size (buf_t *buf, int request_size) { int next_action_pos; /* For simplicity, the number of bytes played must satisfy the following requirements: 1. Do not extract more bytes than are stored in the buffer. 2. Do not extract more bytes than the requested number of bytes. 3. Do not run off the end of the buffer. 4. Do not go past the next action. */ if (buf->actions != NULL) { next_action_pos = buf->actions->position; return MIN4(buf->curfill, request_size, buf->size - buf->start, next_action_pos - buf->position); } else return MIN3(buf->curfill, request_size, buf->size - buf->start); }
/* make a shape curve from area and aspect ratios */ shape_t *shape_from_aspect(double area, double min, double max, int rotable, int n_orients) { shape_t *shape; double r=1, minx, maxx, tmin, tmax; int i, overlap = 0; /* rotatable blocks have 2n no. of orients */ if (n_orients <= 1 || (n_orients & 1)) fatal("n_orients should be an even number greater than 1\n"); shape = (shape_t *) calloc(1, sizeof(shape_t)); if (!shape) fatal("memory allocation error\n"); if (min == max) shape->size = 1 + (!!rotable); else shape->size = n_orients; shape->x = (double *) calloc(shape->size, sizeof(double)); shape->y = (double *) calloc(shape->size, sizeof(double)); if (!shape->x || !shape->y) fatal("memory allocation error\n"); /* overlapping regions of aspect ratios */ if (rotable && min <= 1.0 && max >= 1.0) { overlap = 1; tmin = MIN4(min, max, 1.0/min, 1.0/max); tmax = MAX4(min, max, 1.0/min, 1.0/max); min = tmin; max = tmax; } if (!rotable || overlap) { minx = sqrt(area * min); maxx = sqrt(area * max); if (shape->size > 1) r = pow((maxx / minx) , 1.0/(shape->size-1)); for (i = 0; i < shape->size; i++) { shape->x[i] = minx * pow(r, i); shape->y[i] = area / shape->x[i]; } /* rotable but no overlap, hence two sets of orientations */ } else { int n = shape->size / 2; /* orientations with aspect ratios < 1 */ tmin = MIN(min, 1.0/min); tmax = MIN(max, 1.0/max); minx = sqrt(area * MIN(tmin, tmax)); maxx = sqrt(area * MAX(tmin, tmax)); if ( n > 1) r = pow((maxx / minx) , 1.0/(n-1)); for (i = 0; i < n; i++) { shape->x[i] = minx * pow(r, i); shape->y[i] = area / shape->x[i]; } /* orientations with aspect ratios > 1 */ tmin = MAX(min, 1.0/min); tmax = MAX(max, 1.0/max); minx = sqrt(area * MIN(tmin, tmax)); maxx = sqrt(area * MAX(tmin, tmax)); if ( n > 1) r = pow((maxx / minx) , 1.0/(n-1)); for (i = 0; i < n; i++) { shape->x[n+i] = minx * pow(r, i); shape->y[n+i] = area / shape->x[n+i]; } } return shape; }
static boolean try_setup_line( struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; struct lp_scene *scene = setup->scene; const struct lp_setup_variant_key *key = &setup->setup.variant->key; struct lp_rast_triangle *line; struct lp_rast_plane *plane; struct lp_line_info info; float width = MAX2(1.0, setup->line_width); const struct u_rect *scissor; struct u_rect bbox, bboxpos; boolean s_planes[4]; unsigned tri_bytes; int x[4]; int y[4]; int i; int nr_planes = 4; unsigned viewport_index = 0; unsigned layer = 0; /* linewidth should be interpreted as integer */ int fixed_width = util_iround(width) * FIXED_ONE; float x_offset=0; float y_offset=0; float x_offset_end=0; float y_offset_end=0; float x1diff; float y1diff; float x2diff; float y2diff; float dx, dy; float area; const float (*pv)[4]; boolean draw_start; boolean draw_end; boolean will_draw_start; boolean will_draw_end; if (0) print_line(setup, v1, v2); if (setup->flatshade_first) { pv = v1; } else { pv = v2; } if (setup->viewport_index_slot > 0) { unsigned *udata = (unsigned*)pv[setup->viewport_index_slot]; viewport_index = lp_clamp_viewport_idx(*udata); } if (setup->layer_slot > 0) { layer = *(unsigned*)pv[setup->layer_slot]; layer = MIN2(layer, scene->fb_max_layer); } dx = v1[0][0] - v2[0][0]; dy = v1[0][1] - v2[0][1]; area = (dx * dx + dy * dy); if (area == 0) { LP_COUNT(nr_culled_tris); return TRUE; } info.oneoverarea = 1.0f / area; info.dx = dx; info.dy = dy; info.v1 = v1; info.v2 = v2; /* X-MAJOR LINE */ if (fabsf(dx) >= fabsf(dy)) { float dydx = dy / dx; x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5; y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5; x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5; y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5; if (y2diff==-0.5 && dy<0){ y2diff = 0.5; } /* * Diamond exit rule test for starting point */ if (fabsf(x1diff) + fabsf(y1diff) < 0.5) { draw_start = TRUE; } else if (sign(x1diff) == sign(-dx)) { draw_start = FALSE; } else if (sign(-y1diff) != sign(dy)) { draw_start = TRUE; } else { /* do intersection test */ float yintersect = fracf(v1[0][1]) + x1diff * dydx; draw_start = (yintersect < 1.0 && yintersect > 0.0); } /* * Diamond exit rule test for ending point */ if (fabsf(x2diff) + fabsf(y2diff) < 0.5) { draw_end = FALSE; } else if (sign(x2diff) != sign(-dx)) { draw_end = FALSE; } else if (sign(-y2diff) == sign(dy)) { draw_end = TRUE; } else { /* do intersection test */ float yintersect = fracf(v2[0][1]) + x2diff * dydx; draw_end = (yintersect < 1.0 && yintersect > 0.0); } /* Are we already drawing start/end? */ will_draw_start = sign(-x1diff) != sign(dx); will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0; if (dx < 0) { /* if v2 is to the right of v1, swap pointers */ const float (*temp)[4] = v1; v1 = v2; v2 = temp; dx = -dx; dy = -dy; /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { x_offset_end = - x1diff - 0.5; y_offset_end = x_offset_end * dydx; } if (will_draw_end != draw_end) { x_offset = - x2diff - 0.5; y_offset = x_offset * dydx; } } else{ /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { x_offset = - x1diff + 0.5; y_offset = x_offset * dydx; } if (will_draw_end != draw_end) { x_offset_end = - x2diff + 0.5; y_offset_end = x_offset_end * dydx; } } /* x/y positions in fixed point */ x[0] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset); x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset); x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset); x[3] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset); y[0] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset) - fixed_width/2; y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) - fixed_width/2; y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) + fixed_width/2; y[3] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset) + fixed_width/2; } else { const float dxdy = dx / dy; /* Y-MAJOR LINE */ x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5; y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5; x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5; y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5; if (x2diff==-0.5 && dx<0) { x2diff = 0.5; } /* * Diamond exit rule test for starting point */ if (fabsf(x1diff) + fabsf(y1diff) < 0.5) { draw_start = TRUE; } else if (sign(-y1diff) == sign(dy)) { draw_start = FALSE; } else if (sign(x1diff) != sign(-dx)) { draw_start = TRUE; } else { /* do intersection test */ float xintersect = fracf(v1[0][0]) + y1diff * dxdy; draw_start = (xintersect < 1.0 && xintersect > 0.0); } /* * Diamond exit rule test for ending point */ if (fabsf(x2diff) + fabsf(y2diff) < 0.5) { draw_end = FALSE; } else if (sign(-y2diff) != sign(dy) ) { draw_end = FALSE; } else if (sign(x2diff) == sign(-dx) ) { draw_end = TRUE; } else { /* do intersection test */ float xintersect = fracf(v2[0][0]) + y2diff * dxdy; draw_end = (xintersect < 1.0 && xintersect >= 0.0); } /* Are we already drawing start/end? */ will_draw_start = sign(y1diff) == sign(dy); will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0; if (dy > 0) { /* if v2 is on top of v1, swap pointers */ const float (*temp)[4] = v1; v1 = v2; v2 = temp; dx = -dx; dy = -dy; /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { y_offset_end = - y1diff + 0.5; x_offset_end = y_offset_end * dxdy; } if (will_draw_end != draw_end) { y_offset = - y2diff + 0.5; x_offset = y_offset * dxdy; } } else { /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { y_offset = - y1diff - 0.5; x_offset = y_offset * dxdy; } if (will_draw_end != draw_end) { y_offset_end = - y2diff - 0.5; x_offset_end = y_offset_end * dxdy; } } /* x/y positions in fixed point */ x[0] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset) - fixed_width/2; x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) - fixed_width/2; x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) + fixed_width/2; x[3] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset) + fixed_width/2; y[0] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset); y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset); y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset); y[3] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset); } /* Bounding rectangle (in pixels) */ { /* Yes this is necessary to accurately calculate bounding boxes * with the two fill-conventions we support. GL (normally) ends * up needing a bottom-left fill convention, which requires * slightly different rounding. */ int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; /* Inclusive coordinates: */ bbox.x1--; bbox.y1--; } if (bbox.x1 < bbox.x0 || bbox.y1 < bbox.y0) { if (0) debug_printf("empty bounding box\n"); LP_COUNT(nr_culled_tris); return TRUE; } if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) { if (0) debug_printf("offscreen\n"); LP_COUNT(nr_culled_tris); return TRUE; } bboxpos = bbox; /* Can safely discard negative regions: */ bboxpos.x0 = MAX2(bboxpos.x0, 0); bboxpos.y0 = MAX2(bboxpos.y0, 0); nr_planes = 4; /* * Determine how many scissor planes we need, that is drop scissor * edges if the bounding box of the tri is fully inside that edge. */ if (setup->scissor_test) { /* why not just use draw_regions */ scissor = &setup->scissors[viewport_index]; scissor_planes_needed(s_planes, &bboxpos, scissor); nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3]; } line = lp_setup_alloc_triangle(scene, key->num_inputs, nr_planes, &tri_bytes); if (!line) return FALSE; #ifdef DEBUG line->v[0][0] = v1[0][0]; line->v[1][0] = v2[0][0]; line->v[0][1] = v1[0][1]; line->v[1][1] = v2[0][1]; #endif LP_COUNT(nr_tris); if (lp_context->active_statistics_queries && !llvmpipe_rasterization_disabled(lp_context)) { lp_context->pipeline_statistics.c_primitives++; } /* calculate the deltas */ plane = GET_PLANES(line); plane[0].dcdy = x[0] - x[1]; plane[1].dcdy = x[1] - x[2]; plane[2].dcdy = x[2] - x[3]; plane[3].dcdy = x[3] - x[0]; plane[0].dcdx = y[0] - y[1]; plane[1].dcdx = y[1] - y[2]; plane[2].dcdx = y[2] - y[3]; plane[3].dcdx = y[3] - y[0]; if (draw_will_inject_frontface(lp_context->draw) && setup->face_slot > 0) { line->inputs.frontfacing = v1[setup->face_slot][0]; } else { line->inputs.frontfacing = TRUE; } /* Setup parameter interpolants: */ info.a0 = GET_A0(&line->inputs); info.dadx = GET_DADX(&line->inputs); info.dady = GET_DADY(&line->inputs); info.frontfacing = line->inputs.frontfacing; setup_line_coefficients(setup, &info); line->inputs.disable = FALSE; line->inputs.opaque = FALSE; line->inputs.layer = layer; line->inputs.viewport_index = viewport_index; /* * XXX: this code is mostly identical to the one in lp_setup_tri, except it * uses 4 planes instead of 3. Could share the code (including the sse * assembly, in fact we'd get the 4th plane for free). * The only difference apart from storing the 4th plane would be some * different shuffle for calculating dcdx/dcdy. */ for (i = 0; i < 4; i++) { /* half-edge constants, will be iterated over the whole render * target. */ plane[i].c = IMUL64(plane[i].dcdx, x[i]) - IMUL64(plane[i].dcdy, y[i]); /* correct for top-left vs. bottom-left fill convention. */ if (plane[i].dcdx < 0) { /* both fill conventions want this - adjust for left edges */ plane[i].c++; } else if (plane[i].dcdx == 0) { if (setup->pixel_offset == 0) { /* correct for top-left fill convention: */ if (plane[i].dcdy > 0) plane[i].c++; } else { /* correct for bottom-left fill convention: */ if (plane[i].dcdy < 0) plane[i].c++; } } plane[i].dcdx *= FIXED_ONE; plane[i].dcdy *= FIXED_ONE; /* find trivial reject offsets for each edge for a single-pixel * sized block. These will be scaled up at each recursive level to * match the active blocksize. Scaling in this way works best if * the blocks are square. */ plane[i].eo = 0; if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx; if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy; } /* * When rasterizing scissored tris, use the intersection of the * triangle bounding box and the scissor rect to generate the * scissor planes. * * This permits us to cut off the triangle "tails" that are present * in the intermediate recursive levels caused when two of the * triangles edges don't diverge quickly enough to trivially reject * exterior blocks from the triangle. * * It's not really clear if it's worth worrying about these tails, * but since we generate the planes for each scissored tri, it's * free to trim them in this case. * * Note that otherwise, the scissor planes only vary in 'C' value, * and even then only on state-changes. Could alternatively store * these planes elsewhere. * (Or only store the c value together with a bit indicating which * scissor edge this is, so rasterization would treat them differently * (easier to evaluate) to ordinary planes.) */ if (nr_planes > 4) { struct lp_rast_plane *plane_s = &plane[4]; if (s_planes[0]) { plane_s->dcdx = -1 << 8; plane_s->dcdy = 0; plane_s->c = (1-scissor->x0) << 8; plane_s->eo = 1 << 8; plane_s++; } if (s_planes[1]) { plane_s->dcdx = 1 << 8; plane_s->dcdy = 0; plane_s->c = (scissor->x1+1) << 8; plane_s->eo = 0 << 8; plane_s++; } if (s_planes[2]) { plane_s->dcdx = 0; plane_s->dcdy = 1 << 8; plane_s->c = (1-scissor->y0) << 8; plane_s->eo = 1 << 8; plane_s++; } if (s_planes[3]) { plane_s->dcdx = 0; plane_s->dcdy = -1 << 8; plane_s->c = (scissor->y1+1) << 8; plane_s->eo = 0; plane_s++; } assert(plane_s == &plane[nr_planes]); } return lp_setup_bin_triangle(setup, line, &bbox, &bboxpos, nr_planes, viewport_index); }
static GeglBuffer * gimp_perspective_clone_get_source (GimpSourceCore *source_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, GimpPickable *src_pickable, gint src_offset_x, gint src_offset_y, GeglBuffer *paint_buffer, gint paint_buffer_x, gint paint_buffer_y, gint *paint_area_offset_x, gint *paint_area_offset_y, gint *paint_area_width, gint *paint_area_height, GeglRectangle *src_rect) { GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (source_core); GimpCloneOptions *clone_options = GIMP_CLONE_OPTIONS (paint_options); GeglBuffer *src_buffer; GeglBuffer *dest_buffer; const Babl *src_format_alpha; gint x1d, y1d, x2d, y2d; gdouble x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s; gint xmin, ymin, xmax, ymax; GimpMatrix3 matrix; GimpMatrix3 gegl_matrix; src_buffer = gimp_pickable_get_buffer (src_pickable); src_format_alpha = gimp_pickable_get_format_with_alpha (src_pickable); /* Destination coordinates that will be painted */ x1d = paint_buffer_x; y1d = paint_buffer_y; x2d = paint_buffer_x + gegl_buffer_get_width (paint_buffer); y2d = paint_buffer_y + gegl_buffer_get_height (paint_buffer); /* Boundary box for source pixels to copy: Convert all the vertex of * the box to paint in destination area to its correspondent in * source area bearing in mind perspective */ gimp_perspective_clone_get_source_point (clone, x1d, y1d, &x1s, &y1s); gimp_perspective_clone_get_source_point (clone, x1d, y2d, &x2s, &y2s); gimp_perspective_clone_get_source_point (clone, x2d, y1d, &x3s, &y3s); gimp_perspective_clone_get_source_point (clone, x2d, y2d, &x4s, &y4s); xmin = floor (MIN4 (x1s, x2s, x3s, x4s)); ymin = floor (MIN4 (y1s, y2s, y3s, y4s)); xmax = ceil (MAX4 (x1s, x2s, x3s, x4s)); ymax = ceil (MAX4 (y1s, y2s, y3s, y4s)); switch (clone_options->clone_type) { case GIMP_IMAGE_CLONE: if (! gimp_rectangle_intersect (xmin, ymin, xmax - xmin, ymax - ymin, 0, 0, gegl_buffer_get_width (src_buffer), gegl_buffer_get_height (src_buffer), NULL, NULL, NULL, NULL)) { /* if the source area is completely out of the image */ return NULL; } break; case GIMP_PATTERN_CLONE: gegl_node_set (clone->crop, "x", (gdouble) xmin, "y", (gdouble) ymin, "width", (gdouble) xmax - xmin, "height", (gdouble) ymax - ymin, NULL); break; } dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d), src_format_alpha); gimp_perspective_clone_get_matrix (clone, &matrix); gimp_matrix3_identity (&gegl_matrix); gimp_matrix3_mult (&matrix, &gegl_matrix); gimp_matrix3_translate (&gegl_matrix, -x1d, -y1d); gimp_gegl_node_set_matrix (clone->transform_node, &gegl_matrix); gegl_node_set (clone->dest_node, "buffer", dest_buffer, NULL); gegl_node_blit (clone->dest_node, 1.0, GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d), NULL, NULL, 0, GEGL_BLIT_DEFAULT); *src_rect = *GEGL_RECTANGLE (0, 0, x2d - x1d, y2d - y1d); return dest_buffer; }
void AffineUnit::process_package(LoadPackage *package) { AffinePackage *pkg = (AffinePackage*)package; int min_in_x = server->in_x; int min_in_y = server->in_y; int max_in_x = server->in_x + server->in_w - 1; int max_in_y = server->in_y + server->in_h - 1; int min_out_x = server->out_x; int min_out_y = server->out_y; int max_out_x = server->out_x + server->out_w; int max_out_y = server->out_y + server->out_h; // Amount to shift the input coordinates relative to the output coordinates // To get the pivots to line up int pivot_offset_x = server->in_pivot_x - server->out_pivot_x; int pivot_offset_y = server->in_pivot_y - server->out_pivot_y; // Calculate real coords float out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4; if(server->mode == AffineEngine::STRETCH || server->mode == AffineEngine::PERSPECTIVE || server->mode == AffineEngine::ROTATE) { out_x1 = (float)server->in_x + (float)server->x1 * server->in_w / 100; out_y1 = (float)server->in_y + (float)server->y1 * server->in_h / 100; out_x2 = (float)server->in_x + (float)server->x2 * server->in_w / 100; out_y2 = (float)server->in_y + (float)server->y2 * server->in_h / 100; out_x3 = (float)server->in_x + (float)server->x3 * server->in_w / 100; out_y3 = (float)server->in_y + (float)server->y3 * server->in_h / 100; out_x4 = (float)server->in_x + (float)server->x4 * server->in_w / 100; out_y4 = (float)server->in_y + (float)server->y4 * server->in_h / 100; } else { out_x1 = (float)server->in_x + (float)server->x1 * server->in_w / 100; out_y1 = server->in_y; out_x2 = out_x1 + server->in_w; out_y2 = server->in_y; out_x4 = (float)server->in_x + (float)server->x4 * server->in_w / 100; out_y4 = server->in_y + server->in_h; out_x3 = out_x4 + server->in_w; out_y3 = server->in_y + server->in_h; } // Rotation with OpenGL uses a simple quad. if(server->mode == AffineEngine::ROTATE && server->use_opengl) { #ifdef HAVE_GL server->output->to_texture(); server->output->enable_opengl(); server->output->init_screen(); server->output->bind_texture(0); server->output->clear_pbuffer(); int texture_w = server->output->get_texture_w(); int texture_h = server->output->get_texture_h(); float output_h = server->output->get_h(); float in_x1 = (float)server->in_x / texture_w; float in_x2 = (float)(server->in_x + server->in_w) / texture_w; float in_y1 = (float)server->in_y / texture_h; float in_y2 = (float)(server->in_y + server->in_h) / texture_h; glBegin(GL_QUADS); glNormal3f(0, 0, 1.0); glTexCoord2f(in_x1, in_y1); glVertex3f(out_x1, -output_h+out_y1, 0); glTexCoord2f(in_x2, in_y1); glVertex3f(out_x2, -output_h+out_y2, 0); glTexCoord2f(in_x2, in_y2); glVertex3f(out_x3, -output_h+out_y3, 0); glTexCoord2f(in_x1, in_y2); glVertex3f(out_x4, -output_h+out_y4, 0); glEnd(); server->output->set_opengl_state(VFrame::SCREEN); #endif } else if(server->mode == AffineEngine::PERSPECTIVE || server->mode == AffineEngine::SHEER || server->mode == AffineEngine::ROTATE) { AffineMatrix matrix; float temp; // swap points 3 & 4 temp = out_x4; out_x4 = out_x3; out_x3 = temp; temp = out_y4; out_y4 = out_y3; out_y3 = temp; calculate_matrix( server->in_x, server->in_y, server->in_x + server->in_w, server->in_y + server->in_h, out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4, &matrix); int interpolate = 1; int reverse = !server->forward; float tx, ty, tw; float xinc, yinc, winc; AffineMatrix m, im; float ttx = 0, tty = 0; int itx = 0, ity = 0; int tx1 = 0, ty1 = 0, tx2 = 0, ty2 = 0; if(reverse) { m.copy_from(&matrix); m.invert(&im); matrix.copy_from(&im); } else { matrix.invert(&m); } float dx1 = 0, dy1 = 0; float dx2 = 0, dy2 = 0; float dx3 = 0, dy3 = 0; float dx4 = 0, dy4 = 0; matrix.transform_point(server->in_x, server->in_y, &dx1, &dy1); matrix.transform_point(server->in_x + server->in_w, server->in_y, &dx2, &dy2); matrix.transform_point(server->in_x, server->in_y + server->in_h, &dx3, &dy3); matrix.transform_point(server->in_x + server->in_w, server->in_y + server->in_h, &dx4, &dy4); if(server->use_opengl) { #ifdef HAVE_GL static char *affine_frag = (char*)"uniform sampler2D tex;\n" "uniform mat3 affine_matrix;\n" "uniform vec2 texture_extents;\n" "uniform vec2 image_extents;\n" "uniform vec4 border_color;\n" "void main()\n" "{\n" " vec2 outcoord = gl_TexCoord[0].st;\n" " outcoord *= texture_extents;\n" " mat3 coord_matrix = mat3(\n" " outcoord.x, outcoord.y, 1.0, \n" " outcoord.x, outcoord.y, 1.0, \n" " outcoord.x, outcoord.y, 1.0);\n" " mat3 incoord_matrix = affine_matrix * coord_matrix;\n" " vec2 incoord = vec2(incoord_matrix[0][0], incoord_matrix[0][1]);\n" " incoord /= incoord_matrix[0][2];\n" " incoord /= texture_extents;\n" " if(incoord.x > image_extents.x || incoord.y > image_extents.y)\n" " gl_FragColor = border_color;\n" " else\n" " gl_FragColor = texture2D(tex, incoord);\n" "}\n"; float affine_matrix[9] = { (float)m.values[0][0], (float)m.values[1][0], (float)m.values[2][0], (float)m.values[0][1], (float)m.values[1][1], (float)m.values[2][1], (float)m.values[0][2], (float)m.values[1][2], (float)m.values[2][2] }; server->output->to_texture(); server->output->enable_opengl(); unsigned int frag_shader = VFrame::make_shader(0, affine_frag, 0); if(frag_shader > 0) { glUseProgram(frag_shader); glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); glUniformMatrix3fv(glGetUniformLocation(frag_shader, "affine_matrix"), 1, 0, affine_matrix); glUniform2f(glGetUniformLocation(frag_shader, "texture_extents"), (GLfloat)server->output->get_texture_w(), (GLfloat)server->output->get_texture_h()); glUniform2f(glGetUniformLocation(frag_shader, "image_extents"), (GLfloat)server->output->get_w() / server->output->get_texture_w(), (GLfloat)server->output->get_h() / server->output->get_texture_h()); float border_color[] = { 0, 0, 0, 0 }; if(BC_CModels::is_yuv(server->output->get_color_model())) { border_color[1] = 0.5; border_color[2] = 0.5; } if(!BC_CModels::has_alpha(server->output->get_color_model())) { border_color[3] = 1.0; } glUniform4fv(glGetUniformLocation(frag_shader, "border_color"), 1, (GLfloat*)border_color); server->output->init_screen(); server->output->bind_texture(0); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); server->output->draw_texture(); glUseProgram(0); server->output->set_opengl_state(VFrame::SCREEN); } return; #endif // HAVE_GL } #define ROUND(x) ((int)((x > 0) ? (x) + 0.5 : (x) - 0.5)) #define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) #define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) tx1 = ROUND(MIN4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); ty1 = ROUND(MIN4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); tx2 = ROUND(MAX4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); ty2 = ROUND(MAX4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); CLAMP(ty1, pkg->y1, pkg->y2); CLAMP(ty2, pkg->y1, pkg->y2); CLAMP(tx1, server->out_x, server->out_x + server->out_w); CLAMP(tx2, server->out_x, server->out_x + server->out_w); xinc = m.values[0][0]; yinc = m.values[1][0]; winc = m.values[2][0]; #define CUBIC_ROW(in_row, chroma_offset) \ transform_cubic(dx, \ in_row[col1_offset] - chroma_offset, \ in_row[col2_offset] - chroma_offset, \ in_row[col3_offset] - chroma_offset, \ in_row[col4_offset] - chroma_offset) #define TRANSFORM(components, type, temp_type, chroma_offset, max) \ { \ type **in_rows = (type**)server->input->get_rows(); \ float round_factor = 0.0; \ if(sizeof(type) < 4) round_factor = 0.5; \ for(int y = ty1; y < ty2; y++) \ { \ type *out_row = (type*)server->output->get_rows()[y]; \ \ if(!interpolate) \ { \ tx = xinc * (tx1 + 0.5) + \ m.values[0][1] * (y + pivot_offset_y + 0.5) + \ m.values[0][2] + \ pivot_offset_x * xinc; \ ty = yinc * (tx1 + 0.5) + \ m.values[1][1] * (y + pivot_offset_y + 0.5) + \ m.values[1][2] + \ pivot_offset_x * yinc; \ tw = winc * (tx1 + 0.5) + \ m.values[2][1] * (y + pivot_offset_y + 0.5) + \ m.values[2][2] + \ pivot_offset_x * winc; \ } \ else \ { \ tx = xinc * tx1 + \ m.values[0][1] * (y + pivot_offset_y) + \ m.values[0][2] + \ pivot_offset_x * xinc; \ ty = yinc * tx1 + \ m.values[1][1] * (y + pivot_offset_y) + \ m.values[1][2] + \ pivot_offset_x * yinc; \ tw = winc * tx1 + \ m.values[2][1] * (y + pivot_offset_y) + \ m.values[2][2] + \ pivot_offset_x * winc; \ } \ \ out_row += tx1 * components; \ for(int x = tx1; x < tx2; x++) \ { \ /* Normalize homogeneous coords */ \ if(tw == 0.0) \ { \ ttx = 0.0; \ tty = 0.0; \ } \ else \ if(tw != 1.0) \ { \ ttx = tx / tw; \ tty = ty / tw; \ } \ else \ { \ ttx = tx; \ tty = ty; \ } \ itx = (int)ttx; \ ity = (int)tty; \ \ int row1 = ity - 1; \ int row2 = ity; \ int row3 = ity + 1; \ int row4 = ity + 2; \ CLAMP(row1, min_in_y, max_in_y); \ CLAMP(row2, min_in_y, max_in_y); \ CLAMP(row3, min_in_y, max_in_y); \ CLAMP(row4, min_in_y, max_in_y); \ \ /* Set destination pixels if in clipping region */ \ if(!interpolate && \ x >= min_out_x && \ x < max_out_x) \ { \ if(itx >= min_in_x && \ itx <= max_in_x && \ ity >= min_in_y && \ ity <= max_in_y) \ { \ type *src = in_rows[ity] + itx * components; \ *out_row++ = *src++; \ *out_row++ = *src++; \ *out_row++ = *src++; \ if(components == 4) *out_row++ = *src; \ } \ else \ /* Fill with chroma */ \ { \ *out_row++ = 0; \ *out_row++ = chroma_offset; \ *out_row++ = chroma_offset; \ if(components == 4) *out_row++ = 0; \ } \ } \ else \ /* Bicubic algorithm */ \ if(interpolate && \ x >= min_out_x && \ x < max_out_x) \ { \ /* clipping region */ \ if ((itx + 2) >= min_in_x && \ (itx - 1) <= max_in_x && \ (ity + 2) >= min_in_y && \ (ity - 1) <= max_in_y) \ { \ float dx, dy; \ \ /* the fractional error */ \ dx = ttx - itx; \ dy = tty - ity; \ \ /* Row and column offsets in cubic block */ \ int col1 = itx - 1; \ int col2 = itx; \ int col3 = itx + 1; \ int col4 = itx + 2; \ CLAMP(col1, min_in_x, max_in_x); \ CLAMP(col2, min_in_x, max_in_x); \ CLAMP(col3, min_in_x, max_in_x); \ CLAMP(col4, min_in_x, max_in_x); \ int col1_offset = col1 * components; \ int col2_offset = col2 * components; \ int col3_offset = col3 * components; \ int col4_offset = col4 * components; \ \ type *row1_ptr = in_rows[row1]; \ type *row2_ptr = in_rows[row2]; \ type *row3_ptr = in_rows[row3]; \ type *row4_ptr = in_rows[row4]; \ temp_type r, g, b, a; \ \ r = (temp_type)(transform_cubic(dy, \ CUBIC_ROW(row1_ptr, 0x0), \ CUBIC_ROW(row2_ptr, 0x0), \ CUBIC_ROW(row3_ptr, 0x0), \ CUBIC_ROW(row4_ptr, 0x0)) + \ round_factor); \ \ row1_ptr++; \ row2_ptr++; \ row3_ptr++; \ row4_ptr++; \ g = (temp_type)(transform_cubic(dy, \ CUBIC_ROW(row1_ptr, chroma_offset), \ CUBIC_ROW(row2_ptr, chroma_offset), \ CUBIC_ROW(row3_ptr, chroma_offset), \ CUBIC_ROW(row4_ptr, chroma_offset)) + \ round_factor); \ g += chroma_offset; \ \ row1_ptr++; \ row2_ptr++; \ row3_ptr++; \ row4_ptr++; \ b = (temp_type)(transform_cubic(dy, \ CUBIC_ROW(row1_ptr, chroma_offset), \ CUBIC_ROW(row2_ptr, chroma_offset), \ CUBIC_ROW(row3_ptr, chroma_offset), \ CUBIC_ROW(row4_ptr, chroma_offset)) + \ round_factor); \ b += chroma_offset; \ \ if(components == 4) \ { \ row1_ptr++; \ row2_ptr++; \ row3_ptr++; \ row4_ptr++; \ a = (temp_type)(transform_cubic(dy, \ CUBIC_ROW(row1_ptr, 0x0), \ CUBIC_ROW(row2_ptr, 0x0), \ CUBIC_ROW(row3_ptr, 0x0), \ CUBIC_ROW(row4_ptr, 0x0)) + \ round_factor); \ } \ \ if(sizeof(type) < 4) \ { \ *out_row++ = CLIP(r, 0, max); \ *out_row++ = CLIP(g, 0, max); \ *out_row++ = CLIP(b, 0, max); \ if(components == 4) *out_row++ = CLIP(a, 0, max); \ } \ else \ { \ *out_row++ = r; \ *out_row++ = g; \ *out_row++ = b; \ if(components == 4) *out_row++ = a; \ } \ } \ else \ /* Fill with chroma */ \ { \ *out_row++ = 0; \ *out_row++ = chroma_offset; \ *out_row++ = chroma_offset; \ if(components == 4) *out_row++ = 0; \ } \ } \ else \ { \ out_row += components; \ } \ \ /* increment the transformed coordinates */ \ tx += xinc; \ ty += yinc; \ tw += winc; \ } \ } \ } switch(server->input->get_color_model()) { case BC_RGB_FLOAT: TRANSFORM(3, float, float, 0x0, 1.0) break; case BC_RGB888: TRANSFORM(3, unsigned char, int, 0x0, 0xff) break; case BC_RGBA_FLOAT: TRANSFORM(4, float, float, 0x0, 1.0) break; case BC_RGBA8888: TRANSFORM(4, unsigned char, int, 0x0, 0xff) break; case BC_YUV888: { unsigned char **in_rows = (unsigned char**)server->input->get_rows(); float round_factor = 0.0; if(sizeof(unsigned char) < 4) round_factor = 0.5; for(int y = ty1; y < ty2; y++) { unsigned char *out_row = (unsigned char*)server->output->get_rows()[y]; if(!interpolate) { tx = xinc * (tx1 + 0.5) + m.values[0][1] * (y + pivot_offset_y + 0.5) + m.values[0][2] + pivot_offset_x * xinc; ty = yinc * (tx1 + 0.5) + m.values[1][1] * (y + pivot_offset_y + 0.5) + m.values[1][2] + pivot_offset_x * yinc; tw = winc * (tx1 + 0.5) + m.values[2][1] * (y + pivot_offset_y + 0.5) + m.values[2][2] + pivot_offset_x * winc; } else { tx = xinc * tx1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] + pivot_offset_x * xinc; ty = yinc * tx1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] + pivot_offset_x * yinc; tw = winc * tx1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] + pivot_offset_x * winc; } out_row += tx1 * 3; for(int x = tx1; x < tx2; x++) { // Normalize homogeneous coords if(tw == 0.0) { ttx = 0.0; tty = 0.0; } else if(tw != 1.0) { ttx = tx / tw; tty = ty / tw; } else { ttx = tx; tty = ty; } itx = (int)ttx; ity = (int)tty; int row1 = ity - 1; int row2 = ity; int row3 = ity + 1; int row4 = ity + 2; CLAMP(row1, min_in_y, max_in_y); CLAMP(row2, min_in_y, max_in_y); CLAMP(row3, min_in_y, max_in_y); CLAMP(row4, min_in_y, max_in_y); // Set destination pixels if in clipping region if(!interpolate && x >= min_out_x && x < max_out_x) { if(itx >= min_in_x && itx <= max_in_x && ity >= min_in_y && ity <= max_in_y) { unsigned char *src = in_rows[ity] + itx * 3; *out_row++ = *src++; *out_row++ = *src++; *out_row++ = *src++; } else // Fill with chroma { *out_row++ = 0; *out_row++ = 0x80; *out_row++ = 0x80; } } else // Bicubic algorithm if(interpolate && x >= min_out_x && x < max_out_x) { // clipping region if((itx + 2) >= min_in_x && (itx - 1) <= max_in_x && (ity + 2) >= min_in_y && (ity - 1) <= max_in_y) { float dx, dy; // the fractional error dx = ttx - itx; dy = tty - ity; // Row and column offsets in cubic block int col1 = itx - 1; int col2 = itx; int col3 = itx + 1; int col4 = itx + 2; CLAMP(col1, min_in_x, max_in_x); CLAMP(col2, min_in_x, max_in_x); CLAMP(col3, min_in_x, max_in_x); CLAMP(col4, min_in_x, max_in_x); int col1_offset = col1 * 3; int col2_offset = col2 * 3; int col3_offset = col3 * 3; int col4_offset = col4 * 3; unsigned char *row1_ptr = in_rows[row1]; unsigned char *row2_ptr = in_rows[row2]; unsigned char *row3_ptr = in_rows[row3]; unsigned char *row4_ptr = in_rows[row4]; int r, g, b, a; r = (int)(transform_cubic(dy, CUBIC_ROW(row1_ptr, 0x0), CUBIC_ROW(row2_ptr, 0x0), CUBIC_ROW(row3_ptr, 0x0), CUBIC_ROW(row4_ptr, 0x0)) + round_factor); row1_ptr++; row2_ptr++; row3_ptr++; row4_ptr++; g = (int)(transform_cubic(dy, CUBIC_ROW(row1_ptr, 0x80), CUBIC_ROW(row2_ptr, 0x80), CUBIC_ROW(row3_ptr, 0x80), CUBIC_ROW(row4_ptr, 0x80)) + round_factor); g += 0x80; row1_ptr++; row2_ptr++; row3_ptr++; row4_ptr++; b = (int)(transform_cubic(dy, CUBIC_ROW(row1_ptr, 0x80), CUBIC_ROW(row2_ptr, 0x80), CUBIC_ROW(row3_ptr, 0x80), CUBIC_ROW(row4_ptr, 0x80)) + round_factor); b += 0x80; if(sizeof(unsigned char) < 4) { *out_row++ = CLIP(r, 0, 0xff); *out_row++ = CLIP(g, 0, 0xff); *out_row++ = CLIP(b, 0, 0xff); } else { *out_row++ = r; *out_row++ = g; *out_row++ = b; } } else // Fill with chroma { *out_row++ = 0; *out_row++ = 0x80; *out_row++ = 0x80; } } else { out_row += 3; } // increment the transformed coordinates tx += xinc; ty += yinc; tw += winc; } } } break; case BC_YUVA8888: TRANSFORM(4, unsigned char, int, 0x80, 0xff) break; case BC_RGB161616: TRANSFORM(3, uint16_t, int, 0x0, 0xffff) break; case BC_RGBA16161616: TRANSFORM(4, uint16_t, int, 0x0, 0xffff) break; case BC_YUV161616: TRANSFORM(3, uint16_t, int, 0x8000, 0xffff) break; case BC_YUVA16161616: TRANSFORM(4, uint16_t, int, 0x8000, 0xffff) break; } }
static void trace_draw2filled(DNATrace *t, Display *d, Pixmap p, int max, int x0, int xn, int height, double ys, int off) { int i, h = height-1, o; XPoint *xp[4], *xp2[4]; GC gc[4]; TRACE *tr[4]; int ch; gc[0] = t->Agc; gc[1] = t->Cgc; gc[2] = t->Ggc; gc[3] = t->Tgc; tr[0] = &t->read->traceA[x0]; tr[1] = &t->read->traceC[x0]; tr[2] = &t->read->traceG[x0]; tr[3] = &t->read->traceT[x0]; for (ch = 0; ch < 4; ch++) { if (NULL == (xp[ch] = (XPoint *)xmalloc((xn+2) * sizeof(XPoint)))) { return; } xp[ch]++; } o = t->disp_offset * t->scale_x; if (t->read->maxTraceVal) h -= h*(double)off/t->read->maxTraceVal; for (ch = 0; ch < 4; ch++) { TRACE *trp = tr[ch]; XPoint *xpp = xp[ch]; for (i = 0; i < xn; i++, trp++) { xpp[i].x = (int)((x0 + i) * t->scale_x) - o; xpp[i].y = h - ys * (*trp-off); } tr[ch] = trp; } /* Clip off negative X coordinates as this crashes Linux X servers */ for (i = 0; i < xn; i++) { if (xp[0][i].x >= 0 && xp[1][i].x >= 0 && xp[2][i].x >= 0 && xp[3][i].x >= 0) break; } xp2[0] = &xp[0][i]; xp2[1] = &xp[1][i]; xp2[2] = &xp[2][i]; xp2[3] = &xp[3][i]; xn -= i; #if 1 /* Draw first peak as a line and all lower ones as solid */ { int cur_max; int start = 0; i = 1; cur_max = MIN4(xp2,0); do { while (MIN4(xp2,i) == cur_max && i < xn) i++; for (ch = 0; ch < 4; ch++) { if (ch == cur_max) { XDrawLines(d, p, gc[ch], &xp2[ch][start], i-start, CoordModeOrigin); } else { XPoint tmp; tmp = xp2[ch][i]; xp2[ch][start-1].x = xp2[ch][start].x; xp2[ch][start-1].y = h; xp2[ch][i].x = xp2[ch][i-1].x; xp2[ch][i].y = h; XFillPolygon(d, p, gc[ch], &xp2[ch][start-1], i-start+2, Nonconvex, CoordModeOrigin); xp2[ch][i] = tmp; } } start = i; cur_max = MIN4(xp2,i); } while (i < xn); } #endif #if 0 /* Draw all peaks as solid */ for (ch = 0; ch < 4; ch++) { /* XDrawLines(d, p, gc[ch], xp2[ch], xn, CoordModeOrigin); */ xp2[ch][0].y = h; xp2[ch][xn-1].y = h; XFillPolygon(d, p, gc[ch], xp2[ch], xn, Nonconvex, CoordModeOrigin); } #endif for (ch = 0; ch < 4; ch++) { xp[ch]--; xfree(xp[ch]); } }
static boolean try_setup_line( struct lp_setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { struct lp_scene *scene = setup->scene; const struct lp_setup_variant_key *key = &setup->setup.variant->key; struct lp_rast_triangle *line; struct lp_rast_plane *plane; struct lp_line_info info; float width = MAX2(1.0, setup->line_width); struct u_rect bbox; unsigned tri_bytes; int x[4]; int y[4]; int i; int nr_planes = 4; /* linewidth should be interpreted as integer */ int fixed_width = util_iround(width) * FIXED_ONE; float x_offset=0; float y_offset=0; float x_offset_end=0; float y_offset_end=0; float x1diff; float y1diff; float x2diff; float y2diff; float dx, dy; float area; boolean draw_start; boolean draw_end; boolean will_draw_start; boolean will_draw_end; if (0) print_line(setup, v1, v2); if (setup->scissor_test) { nr_planes = 8; } else { nr_planes = 4; } dx = v1[0][0] - v2[0][0]; dy = v1[0][1] - v2[0][1]; area = (dx * dx + dy * dy); if (area == 0) { LP_COUNT(nr_culled_tris); return TRUE; } info.oneoverarea = 1.0f / area; info.dx = dx; info.dy = dy; info.v1 = v1; info.v2 = v2; /* X-MAJOR LINE */ if (fabsf(dx) >= fabsf(dy)) { float dydx = dy / dx; x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5; y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5; x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5; y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5; if (y2diff==-0.5 && dy<0){ y2diff = 0.5; } /* * Diamond exit rule test for starting point */ if (fabsf(x1diff) + fabsf(y1diff) < 0.5) { draw_start = TRUE; } else if (sign(x1diff) == sign(-dx)) { draw_start = FALSE; } else if (sign(-y1diff) != sign(dy)) { draw_start = TRUE; } else { /* do intersection test */ float yintersect = fracf(v1[0][1]) + x1diff * dydx; draw_start = (yintersect < 1.0 && yintersect > 0.0); } /* * Diamond exit rule test for ending point */ if (fabsf(x2diff) + fabsf(y2diff) < 0.5) { draw_end = FALSE; } else if (sign(x2diff) != sign(-dx)) { draw_end = FALSE; } else if (sign(-y2diff) == sign(dy)) { draw_end = TRUE; } else { /* do intersection test */ float yintersect = fracf(v2[0][1]) + x2diff * dydx; draw_end = (yintersect < 1.0 && yintersect > 0.0); } /* Are we already drawing start/end? */ will_draw_start = sign(-x1diff) != sign(dx); will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0; if (dx < 0) { /* if v2 is to the right of v1, swap pointers */ const float (*temp)[4] = v1; v1 = v2; v2 = temp; dx = -dx; dy = -dy; /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { x_offset_end = - x1diff - 0.5; y_offset_end = x_offset_end * dydx; } if (will_draw_end != draw_end) { x_offset = - x2diff - 0.5; y_offset = x_offset * dydx; } } else{ /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { x_offset = - x1diff + 0.5; y_offset = x_offset * dydx; } if (will_draw_end != draw_end) { x_offset_end = - x2diff + 0.5; y_offset_end = x_offset_end * dydx; } } /* x/y positions in fixed point */ x[0] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset); x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset); x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset); x[3] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset); y[0] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset) - fixed_width/2; y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) - fixed_width/2; y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) + fixed_width/2; y[3] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset) + fixed_width/2; } else { const float dxdy = dx / dy; /* Y-MAJOR LINE */ x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5; y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5; x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5; y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5; if (x2diff==-0.5 && dx<0) { x2diff = 0.5; } /* * Diamond exit rule test for starting point */ if (fabsf(x1diff) + fabsf(y1diff) < 0.5) { draw_start = TRUE; } else if (sign(-y1diff) == sign(dy)) { draw_start = FALSE; } else if (sign(x1diff) != sign(-dx)) { draw_start = TRUE; } else { /* do intersection test */ float xintersect = fracf(v1[0][0]) + y1diff * dxdy; draw_start = (xintersect < 1.0 && xintersect > 0.0); } /* * Diamond exit rule test for ending point */ if (fabsf(x2diff) + fabsf(y2diff) < 0.5) { draw_end = FALSE; } else if (sign(-y2diff) != sign(dy) ) { draw_end = FALSE; } else if (sign(x2diff) == sign(-dx) ) { draw_end = TRUE; } else { /* do intersection test */ float xintersect = fracf(v2[0][0]) + y2diff * dxdy; draw_end = (xintersect < 1.0 && xintersect >= 0.0); } /* Are we already drawing start/end? */ will_draw_start = sign(y1diff) == sign(dy); will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0; if (dy > 0) { /* if v2 is on top of v1, swap pointers */ const float (*temp)[4] = v1; v1 = v2; v2 = temp; dx = -dx; dy = -dy; /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { y_offset_end = - y1diff + 0.5; x_offset_end = y_offset_end * dxdy; } if (will_draw_end != draw_end) { y_offset = - y2diff + 0.5; x_offset = y_offset * dxdy; } } else { /* Otherwise shift planes appropriately */ if (will_draw_start != draw_start) { y_offset = - y1diff - 0.5; x_offset = y_offset * dxdy; } if (will_draw_end != draw_end) { y_offset_end = - y2diff - 0.5; x_offset_end = y_offset_end * dxdy; } } /* x/y positions in fixed point */ x[0] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset) - fixed_width/2; x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) - fixed_width/2; x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) + fixed_width/2; x[3] = subpixel_snap(v1[0][0] + x_offset - setup->pixel_offset) + fixed_width/2; y[0] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset); y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset); y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset); y[3] = subpixel_snap(v1[0][1] + y_offset - setup->pixel_offset); } LP_COUNT(nr_tris); /* Bounding rectangle (in pixels) */ { /* Yes this is necessary to accurately calculate bounding boxes * with the two fill-conventions we support. GL (normally) ends * up needing a bottom-left fill convention, which requires * slightly different rounding. */ int adj = (setup->pixel_offset != 0) ? 1 : 0; bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER; /* Inclusive coordinates: */ bbox.x1--; bbox.y1--; } if (bbox.x1 < bbox.x0 || bbox.y1 < bbox.y0) { if (0) debug_printf("empty bounding box\n"); LP_COUNT(nr_culled_tris); return TRUE; } if (!u_rect_test_intersection(&setup->draw_region, &bbox)) { if (0) debug_printf("offscreen\n"); LP_COUNT(nr_culled_tris); return TRUE; } /* Can safely discard negative regions: */ bbox.x0 = MAX2(bbox.x0, 0); bbox.y0 = MAX2(bbox.y0, 0); line = lp_setup_alloc_triangle(scene, key->num_inputs, nr_planes, &tri_bytes); if (!line) return FALSE; #ifdef DEBUG line->v[0][0] = v1[0][0]; line->v[1][0] = v2[0][0]; line->v[0][1] = v1[0][1]; line->v[1][1] = v2[0][1]; #endif /* calculate the deltas */ plane = GET_PLANES(line); plane[0].dcdy = x[0] - x[1]; plane[1].dcdy = x[1] - x[2]; plane[2].dcdy = x[2] - x[3]; plane[3].dcdy = x[3] - x[0]; plane[0].dcdx = y[0] - y[1]; plane[1].dcdx = y[1] - y[2]; plane[2].dcdx = y[2] - y[3]; plane[3].dcdx = y[3] - y[0]; /* Setup parameter interpolants: */ info.a0 = GET_A0(&line->inputs); info.dadx = GET_DADX(&line->inputs); info.dady = GET_DADY(&line->inputs); setup_line_coefficients(setup, &info); line->inputs.frontfacing = TRUE; line->inputs.disable = FALSE; line->inputs.opaque = FALSE; for (i = 0; i < 4; i++) { /* half-edge constants, will be interated over the whole render * target. */ plane[i].c = plane[i].dcdx * x[i] - plane[i].dcdy * y[i]; /* correct for top-left vs. bottom-left fill convention. * * note that we're overloading gl_rasterization_rules to mean * both (0.5,0.5) pixel centers *and* bottom-left filling * convention. * * GL actually has a top-left filling convention, but GL's * notion of "top" differs from gallium's... * * Also, sometimes (in FBO cases) GL will render upside down * to its usual method, in which case it will probably want * to use the opposite, top-left convention. */ if (plane[i].dcdx < 0) { /* both fill conventions want this - adjust for left edges */ plane[i].c++; } else if (plane[i].dcdx == 0) { if (setup->pixel_offset == 0) { /* correct for top-left fill convention: */ if (plane[i].dcdy > 0) plane[i].c++; } else { /* correct for bottom-left fill convention: */ if (plane[i].dcdy < 0) plane[i].c++; } } plane[i].dcdx *= FIXED_ONE; plane[i].dcdy *= FIXED_ONE; /* find trivial reject offsets for each edge for a single-pixel * sized block. These will be scaled up at each recursive level to * match the active blocksize. Scaling in this way works best if * the blocks are square. */ plane[i].eo = 0; if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx; if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy; } /* * When rasterizing scissored tris, use the intersection of the * triangle bounding box and the scissor rect to generate the * scissor planes. * * This permits us to cut off the triangle "tails" that are present * in the intermediate recursive levels caused when two of the * triangles edges don't diverge quickly enough to trivially reject * exterior blocks from the triangle. * * It's not really clear if it's worth worrying about these tails, * but since we generate the planes for each scissored tri, it's * free to trim them in this case. * * Note that otherwise, the scissor planes only vary in 'C' value, * and even then only on state-changes. Could alternatively store * these planes elsewhere. */ if (nr_planes == 8) { const struct u_rect *scissor = &setup->scissor; plane[4].dcdx = -1; plane[4].dcdy = 0; plane[4].c = 1-scissor->x0; plane[4].eo = 1; plane[5].dcdx = 1; plane[5].dcdy = 0; plane[5].c = scissor->x1+1; plane[5].eo = 0; plane[6].dcdx = 0; plane[6].dcdy = 1; plane[6].c = 1-scissor->y0; plane[6].eo = 1; plane[7].dcdx = 0; plane[7].dcdy = -1; plane[7].c = scissor->y1+1; plane[7].eo = 0; } return lp_setup_bin_triangle(setup, line, &bbox, nr_planes); }
int calculate(int len, int nThreads) { int b, i, j; #ifdef _OPENMP if (nThreads>0) omp_set_num_threads(nThreads); #endif #ifdef _OPENMP #pragma omp parallel #pragma omp master fprintf(stdout,"Thread count: %3d \n",omp_get_num_threads()); #endif for (b = TURN+1; b <= len-1; b++) { #ifdef _OPENMP #pragma omp parallel for private (i,j) schedule(guided) #endif for (i = 1; i <= len - b; i++) { j = i + b; int flag = 0, newWM = INFINITY_; if (canPair(RNA[i], RNA[j])) { flag = 1; int eh = canHairpin(i,j)?eH(i,j):INFINITY_; //hair pin int es = canStack(i,j)?eS(i,j)+getShapeEnergy(i)+getShapeEnergy(j)+V(i+1,j-1):INFINITY_; // stack if (j-i > 6) { // Internal Loop BEGIN int p=0, q=0; int VBIij = INFINITY_; for (p = i+1; p <= MIN(j-2-TURN,i+MAXLOOP+1) ; p++) { int minq = j-i+p-MAXLOOP-2; if (minq < p+1+TURN) minq = p+1+TURN; int maxq = (p==i+1)?(j-2):(j-1); for (q = minq; q <= maxq; q++) { if (!canPair(RNA[p], RNA[q])) continue; if (!canILoop(i,j,p,q)) continue; VBIij = MIN(eL(i, j, p, q) + V(p,q), VBIij); } } VBI(i,j) = VBIij; V(i,j) = V(i,j) + getShapeEnergy(i) + getShapeEnergy(j); } // Internal Loop END if (j-i > 10) { // Multi Loop BEGIN int h; int VMij, VMijd, VMidj, VMidjd; VMij = VMijd = VMidj = VMidjd = INFINITY_; for (h = i+TURN+1; h <= j-1-TURN; h++) { VMij = MIN(VMij, WMU(i+1,h-1) + WML(h,j-1)); VMidj = MIN(VMidj, WMU(i+2,h-1) + WML(h,j-1)); VMijd = MIN(VMijd, WMU(i+1,h-1) + WML(h,j-2)); VMidjd = MIN(VMidjd, WMU(i+2,h-1) + WML(h,j-2)); } int d3 = canSS(j-1)?Ed3(i,j,j-1):INFINITY_; int d5 = canSS(i+1)?Ed5(i,j,i+1):INFINITY_; VMij = MIN(VMij, (VMidj + d5 +Ec)) ; VMij = MIN(VMij, (VMijd + d3 +Ec)); VMij = MIN(VMij, (VMidjd + d5 + d3+ 2*Ec)); VMij = VMij + Ea + Eb + auPenalty(i,j); VM(i,j) = canStack(i,j)?VMij:INFINITY_; } // Multi Loop END V(i,j) = MIN4(eh,es,VBI(i,j),VM(i,j)); } else V(i,j) = INFINITY_; if (j-i > 4) { // WM BEGIN int h; for (h = i+TURN+1 ; h <= j-TURN-1; h++) { //ZS: This sum corresponds to when i,j are NOT paired with each other. //So we need to make sure only terms where i,j aren't pairing are considered. newWM = (!forcePair(i,j))?MIN(newWM, WMU(i,h-1) + WML(h,j)):newWM; } newWM = MIN(V(i,j) + auPenalty(i,j) + Eb, newWM); newWM = canSS(i)?MIN(V(i+1,j) + Ed3(j,i+1,i) + auPenalty(i+1,j) + Eb + Ec, newWM):newWM; //i dangle newWM = canSS(j)?MIN(V(i,j-1) + Ed5(j-1,i,j) + auPenalty(i,j-1) + Eb + Ec, newWM):newWM; //j dangle newWM = (canSS(i)&&canSS(j))?MIN(V(i+1,j-1) + Ed3(j-1,i+1,i) + Ed5(j-1,i+1,j) + auPenalty(i+1,j-1) + Eb + 2*Ec, newWM):newWM; //i,j dangle newWM = canSS(i)?MIN(WMU(i+1,j) + Ec, newWM):newWM; //i dangle newWM = canSS(j)?MIN(WML(i,j-1) + Ec, newWM):newWM; //j dangle WMU(i,j) = WML(i,j) = newWM; } // WM END } } for (j = TURN+2; j <= len; j++) { int i, Wj, Widjd, Wijd, Widj, Wij, Wim1; Wj = INFINITY_; for (i = 1; i < j-TURN; i++) { Wij = Widjd = Wijd = Widj = INFINITY_; Wim1 = MIN(0, W[i-1]); Wij = V(i, j) + auPenalty(i, j) + Wim1; Widjd = (canSS(i)&&canSS(j))?V(i+1,j-1) + auPenalty(i+1,j-1) + Ed3(j-1,i + 1,i) + Ed5(j-1,i+1,j) + Wim1:Widjd; Wijd = canSS(j)?V(i,j-1) + auPenalty(i,j-1) + Ed5(j-1,i,j) + Wim1:Wijd; Widj = canSS(i)?V(i+1, j) + auPenalty(i+1,j) + Ed3(j,i + 1,i) + Wim1:Widj; Wj = MIN(MIN4(Wij, Widjd, Wijd, Widj), Wj); } W[j] = canSS(j)?MIN(Wj, W[j-1]):Wj; } return W[len]; }
/* this takes the smallest ortho-aligned (the sides of the rectangle are * parallel to the x- and y-axis) rectangle fitting around the points a to d, * checks if the whole rectangle is inside the polygon described by points and * writes it to r if the area is bigger than the rectangle already stored in r. */ static void add_rectangle (Point points[4], Rectangle *r, Point a, Point b, Point c, Point d) { gdouble width; gdouble height; gdouble minx, maxx; gdouble miny, maxy; /* get the orthoaligned (the sides of the rectangle are parallel to the x- * and y-axis) rectangle surrounding the points a to d. */ minx = MIN4 (a.x, b.x, c.x, d.x); maxx = MAX4 (a.x, b.x, c.x, d.x); miny = MIN4 (a.y, b.y, c.y, d.y); maxy = MAX4 (a.y, b.y, c.y, d.y); a.x = minx; a.y = miny; b.x = maxx; b.y = miny; c.x = maxx; c.y = maxy; d.x = minx; d.y = maxy; width = maxx - minx; height = maxy - miny; /* check if this rectangle is inside the polygon "points" */ if (in_poly (points, a) && in_poly (points, b) && in_poly (points, c) && in_poly (points, d)) { gdouble area = width * height; /* check if the new rectangle is larger (in terms of area) * than the currently stored rectangle in r, if yes store * new rectangle to r */ if (r->area <= area) { r->a.x = a.x; r->a.y = a.y; r->b.x = b.x; r->b.y = b.y; r->c.x = c.x; r->c.y = c.y; r->d.x = d.x; r->d.y = d.y; r->area = area; } } }
inline wg_v4sf Recognizer::dtw4(float *s, unsigned int n, float *t0, unsigned int m0, float *t1, unsigned int m1, float *t2, unsigned int m2, float *t3, unsigned int m3) { /* Compare an input sequence with 4 reference sequences. For one column of the DTW matrix, MIN4(m0,m1,m2,m3) cells are calculated using vector instructions. The rest of the cells are calculated sequentially. s: input sequence n: number of vectors in s t0..t3: reference sequences m0..m3: number of vectors in the sequence */ unsigned int i, j, common; wg_v4sf cost; float costf; float *t_start0, *t_start1, *t_start2, *t_start3; wg_v4sf *tmp; wg_v4sf res; t_start0 = t0; t_start1 = t1; t_start2 = t2; t_start3 = t3; /* Initialize the edge cells */ dtw1v[0].v = _mm_set_ps1(0); dtw2v[0].v = _mm_set_ps1(FLT_MAX); for (i=1; i < MAX4(m0,m1,m2,m3); i++) dtw1v[i].v = _mm_set_ps1(FLT_MAX); s += VEC_DIM_MAX; common = MIN4(m0,m1,m2,m3); /* Iterate over columns */ for (i=1; i < n; i++) { t0 = t_start0 + VEC_DIM_MAX; t1 = t_start1 + VEC_DIM_MAX; t2 = t_start2 + VEC_DIM_MAX; t3 = t_start3 + VEC_DIM_MAX; /* Iterate over cells of that column */ /* Process 4 cells at a time in parallel */ for (j=1; j < common; j++) { cost = local_distance4(s, t0, t1, t2, t3); /* Inductive step */ dtw2v[j].v = _mm_add_ps(cost.v, MIN3VEC(dtw2v[j-1].v,dtw1v[j].v,dtw1v[j-1].v)); t0 += VEC_DIM_MAX; t1 += VEC_DIM_MAX; t2 += VEC_DIM_MAX; t3 += VEC_DIM_MAX; } /* The remaining of cells is calculated sequentially */ DTW4_PROCESS_REMAINING(0, m0, t0); DTW4_PROCESS_REMAINING(1, m1, t1); DTW4_PROCESS_REMAINING(2, m2, t2); DTW4_PROCESS_REMAINING(3, m3, t3); SWAP(dtw1v,dtw2v,tmp); dtw2v[0].v = _mm_set_ps1(FLT_MAX); s += VEC_DIM_MAX; } res.s[0] = dtw1v[m0-1].s[0]; res.s[1] = dtw1v[m1-1].s[1]; res.s[2] = dtw1v[m2-1].s[2]; res.s[3] = dtw1v[m3-1].s[3]; return res; }
/* * Get the logical and ink extents of the specified string. */ static DFBResult IDirectFBFont_GetStringExtents( IDirectFBFont *thiz, const char *text, int bytes, DFBRectangle *logical_rect, DFBRectangle *ink_rect ) { DFBResult ret; CoreFont *font; int xbaseline = 0; int ybaseline = 0; DIRECT_INTERFACE_GET_DATA(IDirectFBFont) D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); if (!text) return DFB_INVARG; if (!logical_rect && !ink_rect) return DFB_INVARG; if (bytes < 0) bytes = strlen (text); if (ink_rect) memset (ink_rect, 0, sizeof (DFBRectangle)); font = data->font; dfb_font_lock( font ); if (bytes > 0) { int i, num; unsigned int prev = 0; unsigned int indices[bytes]; /* Decode string to character indices. */ ret = dfb_font_decode_text( font, data->encoding, text, bytes, indices, &num ); if (ret) { dfb_font_unlock( font ); return ret; } for (i=0; i<num; i++) { unsigned int current = indices[i]; CoreGlyphData *glyph; if (dfb_font_get_glyph_data( font, current, 0, &glyph ) == DFB_OK) { // FIXME: support font layers int kx, ky = 0; if (prev && font->GetKerning && font->GetKerning( font, prev, current, &kx, &ky ) == DFB_OK) { xbaseline += kx; ybaseline += ky; } if (ink_rect) { DFBRectangle glyph_rect = { xbaseline + glyph->left, ybaseline + glyph->top, glyph->width, glyph->height}; dfb_rectangle_union (ink_rect, &glyph_rect); } xbaseline += glyph->xadvance; ybaseline += glyph->yadvance; } prev = current; } } if (logical_rect) { // We already have the text baseline vector in (xbaseline,ybaseline). // Now find the ascender and descender vectors: int xascender = font->ascender * font->up_unit_x; int yascender = font->ascender * font->up_unit_y; int xdescender = font->descender * font->up_unit_x; int ydescender = font->descender * font->up_unit_y; // Now find top/bottom left/right points relative to the text: int top_left_x = xascender; int top_left_y = yascender; int bottom_left_x = xdescender; int bottom_left_y = ydescender; int top_right_x = top_left_x + xbaseline; int top_right_y = top_left_y + ybaseline; int bottom_right_x = bottom_left_x + xbaseline; int bottom_right_y = bottom_left_y + ybaseline; // The logical rectangle is the bounding-box of these points: #define MIN4(a,b,c,d) (MIN(MIN((a),(b)),MIN((c),(d)))) #define MAX4(a,b,c,d) (MAX(MAX((a),(b)),MAX((c),(d)))) logical_rect->x = MIN4(top_left_x, bottom_left_x, top_right_x, bottom_right_x); logical_rect->y = MIN4(top_left_y, bottom_left_y, top_right_y, bottom_right_y); logical_rect->w = MAX4(top_left_x, bottom_left_x, top_right_x, bottom_right_x) - logical_rect->x; logical_rect->h = MAX4(top_left_y, bottom_left_y, top_right_y, bottom_right_y) - logical_rect->y; } if (ink_rect) { if (ink_rect->w < 0) { /* PBE FIXME what is this doing? */ ink_rect->x += ink_rect->w; ink_rect->w = -ink_rect->w; } ink_rect->x += font->ascender * font->up_unit_x; ink_rect->y += font->ascender * font->up_unit_y; } dfb_font_unlock( font ); return DFB_OK; }
/* * The state machine looks for (approximately) these Perl regular expressions: * * m|\/\*.*?\*\/| * m|\/\/.*| * m|'.*?'| * m|".*?"| * m|#\s*include\s*"(.*?)"| * m|#\s*include\s*<(.*?>"| * * About 98% of the CPU time is spent here, and most of that is in * the 'start' paragraph. Because the current characters are * in a register, the start loop usually eats 4 or 8 characters * per memory read. The MAX4 and MIN4 tests dispose of most * input characters with 1 or 2 comparisons. */ void state_machine(const char * map, const char * end) { const char * next = map; const char * map_dot; unsigned long __buf = 0; for (;;) { start: GETNEXT __start: if (current > MAX4('/','\'','"','#')) goto start; if (current < MIN4('/','\'','"','#')) goto start; CASE('/', slash); CASE('\'', squote); CASE('"', dquote); CASE('#', pound); goto start; /* // */ slash_slash: GETNEXT CASE('\n', start); NOTCASE('\\', slash_slash); GETNEXT goto slash_slash; /* / */ slash: GETNEXT CASE('/', slash_slash); NOTCASE('*', __start); slash_star_dot_star: GETNEXT __slash_star_dot_star: NOTCASE('*', slash_star_dot_star); GETNEXT NOTCASE('/', __slash_star_dot_star); goto start; /* '.*?' */ squote: GETNEXT CASE('\'', start); NOTCASE('\\', squote); GETNEXT goto squote; /* ".*?" */ dquote: GETNEXT CASE('"', start); NOTCASE('\\', dquote); GETNEXT goto dquote; /* #\s* */ pound: GETNEXT CASE(' ', pound); CASE('\t', pound); CASE('i', pound_i); goto __start; /* #\s*i */ pound_i: GETNEXT NOTCASE('n', __start); GETNEXT NOTCASE('c', __start); GETNEXT NOTCASE('l', __start); GETNEXT NOTCASE('u', __start); GETNEXT NOTCASE('d', __start); GETNEXT NOTCASE('e', __start); goto pound_include; /* #\s*include\s* */ pound_include: GETNEXT CASE(' ', pound_include); CASE('\t', pound_include); map_dot = next; CASE('"', pound_include_dquote); CASE('<', pound_include_langle); goto __start; /* #\s*include\s*"(.*)" */ pound_include_dquote: GETNEXT CASE('\n', start); NOTCASE('"', pound_include_dquote); handle_include(0, map_dot, next - map_dot - 1); goto start; /* #\s*include\s*<(.*)> */ pound_include_langle: GETNEXT CASE('\n', start); NOTCASE('>', pound_include_langle); handle_include(1, map_dot, next - map_dot - 1); goto start; } }
static gboolean gimp_perspective_clone_get_source (GimpSourceCore *source_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, GimpPickable *src_pickable, gint src_offset_x, gint src_offset_y, TempBuf *paint_area, gint *paint_area_offset_x, gint *paint_area_offset_y, gint *paint_area_width, gint *paint_area_height, PixelRegion *srcPR) { GimpPerspectiveClone *clone = GIMP_PERSPECTIVE_CLONE (source_core); GimpPaintCore *paint_core = GIMP_PAINT_CORE (source_core); GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (paint_options); GimpImage *src_image; GimpImage *image; GimpImageType src_type; gint x1d, y1d, x2d, y2d; gdouble x1s, y1s, x2s, y2s, x3s, y3s, x4s, y4s; gint xmin, ymin, xmax, ymax; TileManager *src_tiles; TileManager *orig_tiles; PixelRegion origPR; PixelRegion destPR; GimpMatrix3 matrix; gint bytes; src_image = gimp_pickable_get_image (src_pickable); image = gimp_item_get_image (GIMP_ITEM (drawable)); src_type = gimp_pickable_get_image_type (src_pickable); src_tiles = gimp_pickable_get_tiles (src_pickable); /* Destination coordinates that will be painted */ x1d = paint_area->x; y1d = paint_area->y; x2d = paint_area->x + paint_area->width; y2d = paint_area->y + paint_area->height; /* Boundary box for source pixels to copy: Convert all the vertex of * the box to paint in destination area to its correspondent in * source area bearing in mind perspective */ gimp_perspective_clone_get_source_point (clone, x1d, y1d, &x1s, &y1s); gimp_perspective_clone_get_source_point (clone, x1d, y2d, &x2s, &y2s); gimp_perspective_clone_get_source_point (clone, x2d, y1d, &x3s, &y3s); gimp_perspective_clone_get_source_point (clone, x2d, y2d, &x4s, &y4s); xmin = floor (MIN4 (x1s, x2s, x3s, x4s)); ymin = floor (MIN4 (y1s, y2s, y3s, y4s)); xmax = ceil (MAX4 (x1s, x2s, x3s, x4s)); ymax = ceil (MAX4 (y1s, y2s, y3s, y4s)); xmin = CLAMP (xmin - 1, 0, tile_manager_width (src_tiles)); ymin = CLAMP (ymin - 1, 0, tile_manager_height (src_tiles)); xmax = CLAMP (xmax + 1, 0, tile_manager_width (src_tiles)); ymax = CLAMP (ymax + 1, 0, tile_manager_height (src_tiles)); /* if the source area is completely out of the image */ if (!(xmax - xmin) || !(ymax - ymin)) return FALSE; /* If the source image is different from the destination, * then we should copy straight from the source image * to the canvas. * Otherwise, we need a call to get_orig_image to make sure * we get a copy of the unblemished (offset) image */ if (( options->sample_merged && (src_image != image)) || (! options->sample_merged && (source_core->src_drawable != drawable))) { pixel_region_init (&origPR, src_tiles, xmin, ymin, xmax - xmin, ymax - ymin, FALSE); } else { TempBuf *orig; /* get the original image */ if (options->sample_merged) orig = gimp_paint_core_get_orig_proj (paint_core, src_pickable, xmin, ymin, xmax, ymax); else orig = gimp_paint_core_get_orig_image (paint_core, GIMP_DRAWABLE (src_pickable), xmin, ymin, xmax, ymax); pixel_region_init_temp_buf (&origPR, orig, 0, 0, xmax - xmin, ymax - ymin); } /* copy the original image to a tile manager, adding alpha if needed */ bytes = GIMP_IMAGE_TYPE_BYTES (GIMP_IMAGE_TYPE_WITH_ALPHA (src_type)); orig_tiles = tile_manager_new (xmax - xmin, ymax - ymin, bytes); tile_manager_set_offsets (orig_tiles, xmin, ymin); pixel_region_init (&destPR, orig_tiles, 0, 0, xmax - xmin, ymax - ymin, TRUE); if (bytes > origPR.bytes) add_alpha_region (&origPR, &destPR); else copy_region (&origPR, &destPR); clone->src_area = temp_buf_resize (clone->src_area, tile_manager_bpp (orig_tiles), 0, 0, x2d - x1d, y2d - y1d); pixel_region_init_temp_buf (&destPR, clone->src_area, 0, 0, x2d - x1d, y2d - y1d); gimp_perspective_clone_get_matrix (clone, &matrix); gimp_transform_region (src_pickable, GIMP_CONTEXT (paint_options), orig_tiles, &destPR, x1d, y1d, x2d, y2d, &matrix, GIMP_INTERPOLATION_LINEAR, 0, NULL); tile_manager_unref (orig_tiles); pixel_region_init_temp_buf (srcPR, clone->src_area, 0, 0, x2d - x1d, y2d - y1d); return TRUE; }