static void get_bounding_box (GtkWidget *widget, GdkRectangle *bounds) { 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); x = widget->allocation.x; y = widget->allocation.y; w = widget->allocation.width; h = widget->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; }
static void gimp_overlay_child_transform_bounds (GimpOverlayChild *child, GdkRectangle *bounds_child, GdkRectangle *bounds_box) { gdouble x1, x2, x3, x4; gdouble y1, y2, y3, y4; x1 = bounds_child->x; y1 = bounds_child->y; x2 = bounds_child->x + bounds_child->width; y2 = bounds_child->y; x3 = bounds_child->x; y3 = bounds_child->y + bounds_child->height; x4 = bounds_child->x + bounds_child->width; y4 = bounds_child->y + bounds_child->height; cairo_matrix_transform_point (&child->matrix, &x1, &y1); cairo_matrix_transform_point (&child->matrix, &x2, &y2); cairo_matrix_transform_point (&child->matrix, &x3, &y3); cairo_matrix_transform_point (&child->matrix, &x4, &y4); bounds_box->x = (gint) floor (MIN4 (x1, x2, x3, x4)); bounds_box->y = (gint) floor (MIN4 (y1, y2, y3, y4)); bounds_box->width = (gint) ceil (MAX4 (x1, x2, x3, x4)) - bounds_box->x; bounds_box->height = (gint) ceil (MAX4 (y1, y2, y3, y4)) - bounds_box->y; }
fz_bbox fz_transform_bbox(fz_matrix m, fz_bbox b) { fz_point s, t, u, v; if (fz_is_infinite_bbox(b)) return b; s.x = b.x0; s.y = b.y0; t.x = b.x0; t.y = b.y1; u.x = b.x1; u.y = b.y1; v.x = b.x1; v.y = b.y0; s = fz_transform_point(m, s); t = fz_transform_point(m, t); u = fz_transform_point(m, u); v = fz_transform_point(m, v); b.x0 = MIN4(s.x, t.x, u.x, v.x); b.y0 = MIN4(s.y, t.y, u.y, v.y); b.x1 = MAX4(s.x, t.x, u.x, v.x); b.y1 = MAX4(s.y, t.y, u.y, v.y); return b; }
fz_rect fz_transform_rect(fz_matrix m, fz_rect r) { fz_point s, t, u, v; if (fz_is_infinite_rect(r)) return r; s.x = r.x0; s.y = r.y0; t.x = r.x0; t.y = r.y1; u.x = r.x1; u.y = r.y1; v.x = r.x1; v.y = r.y0; s = fz_transform_point(m, s); t = fz_transform_point(m, t); u = fz_transform_point(m, u); v = fz_transform_point(m, v); r.x0 = MIN4(s.x, t.x, u.x, v.x); r.y0 = MIN4(s.y, t.y, u.y, v.y); r.x1 = MAX4(s.x, t.x, u.x, v.x); r.y1 = MAX4(s.y, t.y, u.y, v.y); return r; }
static void sp_ctrlquadr_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCtrlQuadr *cq = SP_CTRLQUADR(item); item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2); if (SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->update) { SP_CANVAS_ITEM_CLASS(sp_ctrlquadr_parent_class)->update(item, affine, flags); } sp_canvas_item_reset_bounds (item); cq->affine = affine; Geom::Point p1(cq->p1 * affine); Geom::Point p2(cq->p2 * affine); Geom::Point p3(cq->p3 * affine); Geom::Point p4(cq->p4 * affine); item->x1 = (int)(MIN4(p1[Geom::X], p2[Geom::X], p3[Geom::X], p4[Geom::X])); item->y1 = (int)(MIN4(p1[Geom::Y], p2[Geom::Y], p3[Geom::Y], p4[Geom::Y])); item->x2 = (int)(MAX4(p1[Geom::X], p2[Geom::X], p3[Geom::X], p4[Geom::X])); item->y2 = (int)(MAX4(p1[Geom::Y], p2[Geom::Y], p3[Geom::Y], p4[Geom::Y])); item->canvas->requestRedraw((int)item->x1, (int)item->y1, (int)item->x2, (int)item->y2); }
//------------------------------------------------------------------------ // //------------------------------------------------------------------------ void seedChkr2::compSeeds(void) { Datareg2 ®2 = (Datareg2&)data; int i, j; int xdim, ydim; float val[4]; float min4, max4; int nseed; if (verbose) printf("***** Seed Creation\n"); xdim = reg2.dim[0]; ydim = reg2.dim[1]; // proceed through the slices computing seeds nseed=0; // process the k'th slab for (i=0; i<xdim-1; i+=2) for (j=0; j<ydim-1; j+=2) { // load the voxel data reg2.getCellValues(i, j, val); min4 = MIN4(val[0], val[1], val[2], val[3]); max4 = MAX4(val[0], val[1], val[2], val[3]); seeds.AddSeed(reg2.index2cell(i,j), min4, max4); nseed++; } for (i=1; i<xdim-1; i+=2) for (j=1; j<ydim-1; j+=2) { // load the voxel data reg2.getCellValues(i, j, val); min4 = MIN4(val[0], val[1], val[2], val[3]); max4 = MAX4(val[0], val[1], val[2], val[3]); seeds.AddSeed(reg2.index2cell(i,j), min4, max4); nseed++; } if (verbose) printf("computed %d seeds\n", nseed); }
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args) { VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2; int resolu; int dims; int i; float *coord_array, *fp; PyObject *list; float k1[4] = {0.0, 0.0, 0.0, 0.0}; float h1[4] = {0.0, 0.0, 0.0, 0.0}; float k2[4] = {0.0, 0.0, 0.0, 0.0}; float h2[4] = {0.0, 0.0, 0.0, 0.0}; if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier", &vector_Type, &vec_k1, &vector_Type, &vec_h1, &vector_Type, &vec_h2, &vector_Type, &vec_k2, &resolu)) { return NULL; } if (resolu <= 1) { PyErr_SetString(PyExc_ValueError, "resolution must be 2 or over"); return NULL; } if (BaseMath_ReadCallback(vec_k1) == -1 || BaseMath_ReadCallback(vec_h1) == -1 || BaseMath_ReadCallback(vec_k2) == -1 || BaseMath_ReadCallback(vec_h2) == -1) { return NULL; } dims = MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i]; for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i]; for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i]; for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i]; coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier"); for (i = 0; i < dims; i++) { BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims); } list = PyList_New(resolu); fp = coord_array; for (i = 0; i < resolu; i++, fp = fp + dims) { PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, Py_NEW, NULL)); } MEM_freeN(coord_array); return list; }
void gimp_display_shell_rotate_bounds (GimpDisplayShell *shell, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *nx1, gdouble *ny1, gdouble *nx2, gdouble *ny2) { g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); if (shell->rotate_transform) { gdouble tx1 = x1; gdouble ty1 = y1; gdouble tx2 = x1; gdouble ty2 = y2; gdouble tx3 = x2; gdouble ty3 = y1; gdouble tx4 = x2; gdouble ty4 = y2; cairo_matrix_transform_point (shell->rotate_transform, &tx1, &ty1); cairo_matrix_transform_point (shell->rotate_transform, &tx2, &ty2); cairo_matrix_transform_point (shell->rotate_transform, &tx3, &ty3); cairo_matrix_transform_point (shell->rotate_transform, &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); } else { *nx1 = x1; *ny1 = y1; *nx2 = x2; *ny2 = y2; } }
static void gth_transform_resize (cairo_matrix_t *matrix, GthTransformResize resize, cairo_rectangle_int_t *original, cairo_rectangle_int_t *boundary) { int x1, y1, x2, y2; x1 = original->x; y1 = original->y; x2 = original->x + original->width; y2 = original->y + original->height; switch (resize) { case GTH_TRANSFORM_RESIZE_CLIP: /* keep the original size */ break; case GTH_TRANSFORM_RESIZE_BOUNDING_BOX: case GTH_TRANSFORM_RESIZE_CROP: { double dx1, dx2, dx3, dx4; double dy1, dy2, dy3, dy4; _cairo_matrix_transform_point (matrix, x1, y1, &dx1, &dy1); _cairo_matrix_transform_point (matrix, x2, y1, &dx2, &dy2); _cairo_matrix_transform_point (matrix, x1, y2, &dx3, &dy3); _cairo_matrix_transform_point (matrix, x2, y2, &dx4, &dy4); x1 = (int) floor (MIN4 (dx1, dx2, dx3, dx4)); y1 = (int) floor (MIN4 (dy1, dy2, dy3, dy4)); x2 = (int) ceil (MAX4 (dx1, dx2, dx3, dx4)); y2 = (int) ceil (MAX4 (dy1, dy2, dy3, dy4)); break; } } boundary->x = x1; boundary->y = y1; boundary->width = x2 - x1; boundary->height = y2 - y1; }
/* this calculates the smallest rectangle (with sides parallel to x- and * y-axis) that contains the points d1 to d4 */ static void gimp_transform_resize_adjust (gdouble dx1, gdouble dy1, gdouble dx2, gdouble dy2, gdouble dx3, gdouble dy3, gdouble dx4, gdouble dy4, gint *x1, gint *y1, gint *x2, gint *y2) { *x1 = (gint) floor (MIN4 (dx1, dx2, dx3, dx4)); *y1 = (gint) floor (MIN4 (dy1, dy2, dy3, dy4)); *x2 = (gint) ceil (MAX4 (dx1, dx2, dx3, dx4)); *y2 = (gint) ceil (MAX4 (dy1, dy2, dy3, dy4)); }
void gimp_display_shell_untransform_bounds (const GimpDisplayShell *shell, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *nx1, gdouble *ny1, gdouble *nx2, gdouble *ny2) { g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (nx1 != NULL); g_return_if_fail (ny1 != NULL); g_return_if_fail (nx2 != NULL); g_return_if_fail (ny2 != NULL); if (shell->rotate_untransform) { gdouble tx1, ty1; gdouble tx2, ty2; gdouble tx3, ty3; gdouble tx4, ty4; gimp_display_shell_untransform_xy_f (shell, x1, y1, &tx1, &ty1); gimp_display_shell_untransform_xy_f (shell, x1, y2, &tx2, &ty2); gimp_display_shell_untransform_xy_f (shell, x2, y1, &tx3, &ty3); gimp_display_shell_untransform_xy_f (shell, x2, y2, &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); } else { gimp_display_shell_untransform_xy_f (shell, x1, y1, nx1, ny1); gimp_display_shell_untransform_xy_f (shell, x2, y2, nx2, ny2); } }
static void get_bounding_box (GtkWidget *widget, GdkRectangle *bounds) { GtkAllocation allocation; GtkBorder border = { 0, }; 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); if (GTK_IS_WINDOW (widget)) _gtk_window_get_shadow_width (GTK_WINDOW (widget), &border); x = allocation.x + border.left; y = allocation.y + border.right; w = allocation.width - border.left - border.right; h = allocation.height - border.top - border.bottom; 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; }
static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) { VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2; int resolu; int dims; int i; float *coord_array, *fp; PyObject *list; float k1[4] = {0.0, 0.0, 0.0, 0.0}; float h1[4] = {0.0, 0.0, 0.0, 0.0}; float k2[4] = {0.0, 0.0, 0.0, 0.0}; float h2[4] = {0.0, 0.0, 0.0, 0.0}; if( !PyArg_ParseTuple ( args, "O!O!O!O!i", &vector_Type, &vec_k1, &vector_Type, &vec_h1, &vector_Type, &vec_h2, &vector_Type, &vec_k2, &resolu) || (resolu<=1) ) { PyErr_SetString( PyExc_TypeError, "expected 4 vector types and an int greater then 1\n" ); return NULL; } if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2)) return NULL; dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i]; for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i]; for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i]; for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i]; coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp"); for(i=0; i<dims; i++) { forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array+i, resolu-1, sizeof(float)*dims); } list= PyList_New(resolu); fp= coord_array; for(i=0; i<resolu; i++, fp= fp+dims) { PyList_SET_ITEM(list, i, newVectorObject(fp, dims, Py_NEW, NULL)); } MEM_freeN(coord_array); return list; }
static inline void calc_set_num(instr_t *instr, t_glob_reg_state* glob_reg_state ) { int i; //general purpose registers. Instead of using the whole enum, we only need to check for the //largest registers, any overlapping accesses will also trigger. #ifdef X64 update_setnrs(instr, DR_REG_START_64, DR_REG_STOP_64, glob_reg_state); #else update_setnrs(instr, DR_REG_START_32, DR_REG_STOP_32, glob_reg_state); #endif #ifdef CONSIDER_MORE_REGS update_setnrs(instr, DR_REG_START_MMX, DR_REG_STOP_MMX, glob_reg_state); update_setnrs(instr, DR_REG_START_XMM, DR_REG_STOP_XMM, glob_reg_state); update_setnrs(instr, DR_REG_START_YMM, DR_REG_STOP_YMM, glob_reg_state); update_setnrs(instr, DR_REG_START_FLOAT, DR_REG_STOP_FLOAT, glob_reg_state); update_setnrs(instr, DR_REG_START_SEGMENT, DR_REG_START_CR, glob_reg_state); update_setnrs(instr, DR_REG_START_DR, DR_REG_STOP_DR, glob_reg_state); update_setnrs(instr, DR_REG_START_CR, DR_REG_STOP_CR, glob_reg_state); #endif #ifdef CONSIDER_EFLAGS update_eflag_setnrs(instr, glob_reg_state); #endif glob_reg_state->final_setnr = MAX4(glob_reg_state->raw_setnr, glob_reg_state->war_setnr, glob_reg_state->waw_setnr, glob_reg_state->else_setnr); //assigning the set number for (i = 0; i <= DR_REG_LAST_VALID_ENUM; i++) { if ( (i != DR_REG_NULL) && (i != DR_REG_INVALID) ) { if(instr_reads_from_reg(instr, i)) { glob_reg_state->my_readfrom[i] = MAX(glob_reg_state->my_readfrom[i], glob_reg_state->final_setnr); } if(instr_writes_to_reg(instr, i)) { glob_reg_state->my_writtento[i] = MAX(glob_reg_state->my_writtento[i], glob_reg_state->final_setnr); } } } glob_reg_state->num_sets = MAX(glob_reg_state->num_sets, glob_reg_state->final_setnr); }
/* 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; } }
// Fill in traceback matrix static void alignment_fill_matrices(aligner_t *aligner, char is_sw) { score_t *match_scores = aligner->match_scores; score_t *gap_a_scores = aligner->gap_a_scores; score_t *gap_b_scores = aligner->gap_b_scores; const scoring_t *scoring = aligner->scoring; size_t score_width = aligner->score_width; size_t score_height = aligner->score_height; size_t i, j; const score_t min = is_sw ? 0 : SCORE_MIN; size_t seq_i, seq_j, len_i = score_width-1, len_j = score_height-1; size_t index, index_left, index_up, index_upleft; // [0][0] match_scores[0] = 0; gap_a_scores[0] = 0; gap_b_scores[0] = 0; if(is_sw) { for(i = 1; i < score_width; i++) match_scores[i] = gap_a_scores[i] = gap_b_scores[i] = 0; for(j = 1, index = score_width; j < score_height; j++, index += score_width) match_scores[index] = gap_a_scores[index] = gap_b_scores[index] = min; } else { // work along first row -> [i][0] for(i = 1; i < score_width; i++) { match_scores[i] = min; // Think carefully about which way round these are gap_a_scores[i] = min; gap_b_scores[i] = scoring->no_start_gap_penalty ? 0 : scoring->gap_open + (long)i * scoring->gap_extend; } // work down first column -> [0][j] for(j = 1, index = score_width; j < score_height; j++, index += score_width) { match_scores[index] = min; // Think carefully about which way round these are gap_a_scores[index] = scoring->no_start_gap_penalty ? 0 : scoring->gap_open + (long)j * scoring->gap_extend; gap_b_scores[index] = min; } } // These are longs to force addition to be done with higher accuracy long gap_open_penalty = scoring->gap_extend + scoring->gap_open; long gap_extend_penalty = scoring->gap_extend; long substitution_penalty; // start at position [1][1] index_upleft = 0; index_up = 1; index_left = score_width; index = score_width+1; for(seq_j = 0; seq_j < len_j; seq_j++) { for(seq_i = 0; seq_i < len_i; seq_i++) { // Update match_scores[i][j] with position [i-1][j-1] // substitution penalty bool is_match; int tmp_penalty; scoring_lookup(scoring, aligner->seq_a[seq_i], aligner->seq_b[seq_j], &tmp_penalty, &is_match); if(scoring->no_mismatches && !is_match) { match_scores[index] = min; } else { substitution_penalty = tmp_penalty; // cast to long // substitution // 1) continue alignment // 2) close gap in seq_a // 3) close gap in seq_b match_scores[index] = MAX4(match_scores[index_upleft] + substitution_penalty, gap_a_scores[index_upleft] + substitution_penalty, gap_b_scores[index_upleft] + substitution_penalty, min); } // Long arithmetic since some INTs are set to min and penalty is -ve // (adding as ints would cause an integer overflow) // Update gap_a_scores[i][j] from position [i][j-1] if(seq_i == len_i-1 && scoring->no_end_gap_penalty) { gap_a_scores[index] = MAX3(match_scores[index_up], gap_a_scores[index_up], gap_b_scores[index_up]); } else if(!scoring->no_gaps_in_a || seq_i == len_i-1) { gap_a_scores[index] = MAX4(match_scores[index_up] + gap_open_penalty, gap_a_scores[index_up] + gap_extend_penalty, gap_b_scores[index_up] + gap_open_penalty, min); } else gap_a_scores[index] = min; // Update gap_b_scores[i][j] from position [i-1][j] if(seq_j == len_j-1 && scoring->no_end_gap_penalty) { gap_b_scores[index] = MAX3(match_scores[index_left], gap_a_scores[index_left], gap_b_scores[index_left]); } else if(!scoring->no_gaps_in_b || seq_j == len_j-1) { gap_b_scores[index] = MAX4(match_scores[index_left] + gap_open_penalty, gap_a_scores[index_left] + gap_open_penalty, gap_b_scores[index_left] + gap_extend_penalty, min); } else gap_b_scores[index] = min; index++; index_left++; index_up++; index_upleft++; } index++; index_left++; index_up++; index_upleft++; } }
/* * 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; }
float smith_waterman_custom(const char *str1, const char *str2, const void *v_conf) { const sub_cost_t *sub_cost = v_conf; float cost; float max_so_far = (float) 0; int n = strlen(str1); int m = strlen(str2); int i, j; if ((n == 0) || (m == 0)) return ((float) 0); float d[n][m]; for (i = 0; i < n; i++) { cost = sub_cost->cost_func(str1, i, str2, 0); if (i == 0) d[0][0] = MAX3((float)0, -sub_cost->cost->gap_cost, cost); else d[i][0] = MAX3(0, d[i - 1][0] - sub_cost->cost->gap_cost, cost); if (d[i][0] > max_so_far) max_so_far = d[i][0]; } for (j = 0; j < m; j++) { cost = sub_cost->cost_func(str1, 0, str2, j); if (j == 0) d[0][0] = MAX3(0, -sub_cost->cost->gap_cost, cost); else d[0][j] = MAX3(0, d[0][j-1] - sub_cost->cost->gap_cost, cost); if (d[0][j] > max_so_far) max_so_far = d[0][j]; } for (i = 1; i < n; i++) { for (j = 1; j < m; j++) { cost = sub_cost->cost_func(str1, i, str2, j); d[i][j] = MAX4((float)0, (d[i - 1][j] - sub_cost->cost->gap_cost), (d[i][j - 1] - sub_cost->cost->gap_cost), (d[i - 1][j - 1] + cost)); if (d[i][j] > max_so_far) max_so_far = d[i][j]; } } return (max_so_far); }
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); }
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; }
float custom_smith_waterman_gotoh(const char *str1, const char *str2, const w_comp_idx_cost_t *conf) { float cost; float max_so_far = 0; float max_gap_cost = 0; float max_gap_cost1 = 0; float max_gap_cost2 = 0; int n = strlen(str1); int m = strlen(str2); int i, j, k, w_st; if ((n == 0) || (m == 0)) return (float) 0; float d[n][m]; for (i = 0; i < n; i++) { cost = conf->comp_conf->sub_cost->cost_func(str1, i, str2, 0); if (i == 0) d[0][0] = MAX(0, cost); else { w_st = i - conf->win_size; if (w_st < 1) w_st = 1; for (k = w_st; k < i; k++) max_gap_cost = MAX(max_gap_cost, d[i - k][0] - conf->comp_conf->gap_cost->cost_func(i - k, i)); d[i][0] = MAX3(0, max_gap_cost, cost); } if (d[i][0] > max_so_far) max_so_far = d[i][0]; } for (j = 0; j < m; j++) { cost = conf->comp_conf->sub_cost->cost_func(str1, 0, str2, j); if (j == 0) d[0][0] = MAX(0, cost); else { max_gap_cost = 0; w_st = j - conf->win_size; if (w_st < 1) w_st = 1; for (k = w_st; k < j; k++) max_gap_cost = MAX(max_gap_cost, d[0][j - k] - conf->comp_conf->gap_cost->cost_func(j - k, j)); d[0][j] = MAX3(0, max_gap_cost, cost); } if (d[0][j] > max_so_far) max_so_far = d[0][j]; } for (i = 1; i < n; i++) { for (j = 1; j < m; j++) { cost = conf->comp_conf->sub_cost->cost_func(str1, i, str2, j); w_st = i - conf->win_size; if (w_st < 1) w_st = 1; for (k = w_st; k < i; k++) max_gap_cost1 = MAX(max_gap_cost1, d[i - k][j] - conf->comp_conf->gap_cost->cost_func(i - k, i)); w_st = j - conf->win_size; if (w_st < 1) w_st = 1; for (k = w_st; k < j; k++) max_gap_cost2 = MAX(max_gap_cost2, d[i][j-k] - conf->comp_conf->gap_cost->cost_func(j - k, j)); d[i][j] = MAX4(0, max_gap_cost1, max_gap_cost2, d[i - 1][j - 1] + cost); if (d[i][j] > max_so_far) max_so_far = d[i][j]; } } return max_so_far; }
/* 从三个备份中读出一个备份的数据 */ void ReadThreeBackupEnergy(uint ReadAdd1, uint ReadAdd2, uint ReadAdd3, uchar len, uint BackupErrAdd, uint BackupALLErrAdd, uchar *pOut) { uchar bkBlockFlg = 0, bkBlockOk=0, i, tmp; uint eeAddr[3] = {ReadAdd1, ReadAdd2, ReadAdd3}; uchar bkbuf[12]; LowVoltage = 0x55; ThreeBferro = 0x55; WDTE = 0xAC; if(0 == len) { return; } //检查三个备份的数据是否正确,记录在bkBlockFlg中 for(i=0; i<3; i++) { BackupErrAdd += 2*i; //BackupErrAdd的使用情况?E2分配情况? Read512(bkbuf+4*i, eeAddr[i], len); tmp = Check_CS(bkbuf+4*i, len); //检查校验值 if(TRUE == tmp) { bkBlockFlg |= (0x01<<i); } else { bkBlockFlg &= ~(0x01<<i); E2PINC(BackupErrAdd, 2); //对应的错误记录加1 } } //三个备份数据都错误 if(0x00 == bkBlockFlg) { E2PINC(BackupALLErrAdd, 2); ThreeBferro = 0xAA; } switch(bkBlockFlg) { case 0x00: //三备份数据都错误,默认从第一备份读(?) bkBlockOk = BK_1ST; IndexEnergyBackup = BK_2ND; Eeprom_err = Eeprom_err | 4; //用于错误显示等 break; case 0x01: //只第一备份正确 bkBlockOk = BK_1ST; IndexEnergyBackup = BK_2ND; break; case 0x02: bkBlockOk = BK_2ND; IndexEnergyBackup = BK_3RD; break; case 0x04: bkBlockOk = BK_3RD; IndexEnergyBackup = BK_1ST; break; case 0x03: //第一、二备份正确 if(TRUE == Max3(bkbuf, bkbuf+4, 4)) //这个函数后续也改一下命名吧... { bkBlockOk = BK_1ST; } else { bkBlockOk = BK_2ND; } IndexEnergyBackup = BK_3RD; break; case 0x05: //第一、三备份正确 if(TRUE == MAX3(bkbuf, bkbuf+8, 4)) { bkBlockOk = BK_1ST; } else { bkBlockOk = BK_3RD; } IndexEnergyBackup = BK_2ND; break; case 0x06: //第二、三备份正确 if(TRUE == MAX3(bkbuf+4, bkbuf+8, 4)) { bkBlockOk = BK_2ND; } else { bkBlockOk = BK_3RD; } IndexEnergyBackup = BK_1ST; break; case 0x07: //三备份都正确 tmp = MAX4(bkbuf, bkbuf+4, bkbuf+8, 4); //比较三备份谁比较大 if(0x01 == tmp) { bkBlockOk = BK_1ST; IndexEnergyBackup = BK_2ND; } if(0x02 == tmp) { bkBlockOk = BK_2ND; IndexEnergyBackup = BK_3RD; } if(0x03 == tmp) { bkBlockOk = BK_3RD; IndexEnergyBackup = BK_1ST; } break; default: bkBlockOk = BK_1ST; break; } switch(bkBlockOk) { case BK_1ST: xmemcpy(bkbuf, pOut, len); break; case BK_2ND: xmemcpy(bkbuf+4, pOut, len); break; case BK_3RD: xmemcpy(bkbuf+8, pOut, len); break; default: break; } }
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; }
/* 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; } } }
cholmod_sparse *CHOLMOD(ssmult) ( /* ---- input ---- */ cholmod_sparse *A, /* left matrix to multiply */ cholmod_sparse *B, /* right matrix to multiply */ int stype, /* requested stype of C */ int values, /* TRUE: do numerical values, FALSE: pattern only */ int sorted, /* if TRUE then return C with sorted columns */ /* --------------- */ cholmod_common *Common ) { double bjt ; double *Ax, *Bx, *Cx, *W ; Int *Ap, *Anz, *Ai, *Bp, *Bnz, *Bi, *Cp, *Ci, *Flag ; cholmod_sparse *C, *A2, *B2, *A3, *B3, *C2 ; Int apacked, bpacked, j, i, pa, paend, pb, pbend, ncol, mark, cnz, t, p, nrow, anz, bnz, do_swap_and_transpose, n1, n2 ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ RETURN_IF_NULL_COMMON (NULL) ; RETURN_IF_NULL (A, NULL) ; RETURN_IF_NULL (B, NULL) ; values = values && (A->xtype != CHOLMOD_PATTERN) && (B->xtype != CHOLMOD_PATTERN) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ; RETURN_IF_XTYPE_INVALID (B, CHOLMOD_PATTERN, values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ; if (A->ncol != B->nrow) { /* inner dimensions must agree */ ERROR (CHOLMOD_INVALID, "A and B inner dimensions must match") ; return (NULL) ; } /* A and B must have the same numerical type if values is TRUE (both must * be CHOLMOD_REAL, this is implicitly checked above) */ Common->status = CHOLMOD_OK ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ if (A->nrow <= 1) { /* C will be implicitly sorted, so no need to sort it here */ sorted = FALSE ; } if (sorted) { n1 = MAX (A->nrow, B->ncol) ; } else { n1 = A->nrow ; } n2 = MAX4 (A->ncol, A->nrow, B->nrow, B->ncol) ; CHOLMOD(allocate_work) (n1, n2, values ? n1 : 0, Common) ; if (Common->status < CHOLMOD_OK) { /* out of memory */ return (NULL) ; } ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1 : 0, Common)) ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ /* convert A to unsymmetric, if necessary */ A2 = NULL ; B2 = NULL ; if (A->stype) { /* workspace: Iwork (max (A->nrow,A->ncol)) */ A2 = CHOLMOD(copy) (A, 0, values, Common) ; if (Common->status < CHOLMOD_OK) { /* out of memory */ ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; return (NULL) ; } A = A2 ; } /* convert B to unsymmetric, if necessary */ if (B->stype) { /* workspace: Iwork (max (B->nrow,B->ncol)) */ B2 = CHOLMOD(copy) (B, 0, values, Common) ; if (Common->status < CHOLMOD_OK) { /* out of memory */ CHOLMOD(free_sparse) (&A2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; return (NULL) ; } B = B2 ; } ASSERT (CHOLMOD(dump_sparse) (A, "A", Common) >= 0) ; ASSERT (CHOLMOD(dump_sparse) (B, "B", Common) >= 0) ; /* get the A matrix */ Ap = A->p ; Anz = A->nz ; Ai = A->i ; Ax = A->x ; apacked = A->packed ; /* get the B matrix */ Bp = B->p ; Bnz = B->nz ; Bi = B->i ; Bx = B->x ; bpacked = B->packed ; /* get the size of C */ nrow = A->nrow ; ncol = B->ncol ; /* get workspace */ W = Common->Xwork ; /* size nrow, unused if values is FALSE */ Flag = Common->Flag ; /* size nrow, Flag [0..nrow-1] < mark on input*/ /* ---------------------------------------------------------------------- */ /* count the number of entries in the result C */ /* ---------------------------------------------------------------------- */ cnz = 0 ; for (j = 0 ; j < ncol ; j++) { /* clear the Flag array */ /* mark = CHOLMOD(clear_flag) (Common) ; */ CHOLMOD_CLEAR_FLAG (Common) ; mark = Common->mark ; /* for each nonzero B(t,j) in column j, do: */ pb = Bp [j] ; pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; for ( ; pb < pbend ; pb++) { /* B(t,j) is nonzero */ t = Bi [pb] ; /* add the nonzero pattern of A(:,t) to the pattern of C(:,j) */ pa = Ap [t] ; paend = (apacked) ? (Ap [t+1]) : (pa + Anz [t]) ; for ( ; pa < paend ; pa++) { i = Ai [pa] ; if (Flag [i] != mark) { Flag [i] = mark ; cnz++ ; } } } if (cnz < 0) { break ; /* integer overflow case */ } } /* mark = CHOLMOD(clear_flag) (Common) ; */ CHOLMOD_CLEAR_FLAG (Common) ; mark = Common->mark ; /* ---------------------------------------------------------------------- */ /* check for integer overflow */ /* ---------------------------------------------------------------------- */ if (cnz < 0) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; return (NULL) ; } /* ---------------------------------------------------------------------- */ /* Determine how to return C sorted (if requested) */ /* ---------------------------------------------------------------------- */ do_swap_and_transpose = FALSE ; if (sorted) { /* Determine the best way to return C with sorted columns. Computing * C = (B'*A')' takes cnz + anz + bnz time (ignoring O(n) terms). * Sorting C when done, C = (A*B)'', takes 2*cnz time. Pick the one * with the least amount of work. */ anz = CHOLMOD(nnz) (A, Common) ; bnz = CHOLMOD(nnz) (B, Common) ; do_swap_and_transpose = (anz + bnz < cnz) ; if (do_swap_and_transpose) { /* -------------------------------------------------------------- */ /* C = (B'*A')' */ /* -------------------------------------------------------------- */ /* workspace: Iwork (A->nrow) */ A3 = CHOLMOD(ptranspose) (A, values, NULL, NULL, 0, Common) ; CHOLMOD(free_sparse) (&A2, Common) ; A2 = A3 ; if (Common->status < CHOLMOD_OK) { /* out of memory */ CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)); return (NULL) ; } /* workspace: Iwork (B->nrow) */ B3 = CHOLMOD(ptranspose) (B, values, NULL, NULL, 0, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; B2 = B3 ; if (Common->status < CHOLMOD_OK) { /* out of memory */ CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)); return (NULL) ; } A = B2 ; B = A2 ; /* get the new A matrix */ Ap = A->p ; Anz = A->nz ; Ai = A->i ; Ax = A->x ; apacked = A->packed ; /* get the new B matrix */ Bp = B->p ; Bnz = B->nz ; Bi = B->i ; Bx = B->x ; bpacked = B->packed ; /* get the size of C' */ nrow = A->nrow ; ncol = B->ncol ; } } /* ---------------------------------------------------------------------- */ /* allocate C */ /* ---------------------------------------------------------------------- */ C = CHOLMOD(allocate_sparse) (nrow, ncol, cnz, FALSE, TRUE, 0, values ? A->xtype : CHOLMOD_PATTERN, Common) ; if (Common->status < CHOLMOD_OK) { /* out of memory */ CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; return (NULL) ; } Cp = C->p ; Ci = C->i ; Cx = C->x ; /* ---------------------------------------------------------------------- */ /* C = A*B */ /* ---------------------------------------------------------------------- */ cnz = 0 ; if (values) { /* pattern and values */ for (j = 0 ; j < ncol ; j++) { /* clear the Flag array */ /* mark = CHOLMOD(clear_flag (Common)) ; */ CHOLMOD_CLEAR_FLAG (Common) ; mark = Common->mark ; /* start column j of C */ Cp [j] = cnz ; /* for each nonzero B(t,j) in column j, do: */ pb = Bp [j] ; pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; for ( ; pb < pbend ; pb++) { /* B(t,j) is nonzero */ t = Bi [pb] ; bjt = Bx [pb] ; /* add the nonzero pattern of A(:,t) to the pattern of C(:,j) * and scatter the values into W */ pa = Ap [t] ; paend = (apacked) ? (Ap [t+1]) : (pa + Anz [t]) ; for ( ; pa < paend ; pa++) { i = Ai [pa] ; if (Flag [i] != mark) { Flag [i] = mark ; Ci [cnz++] = i ; } W [i] += Ax [pa] * bjt ; } } /* gather the values into C(:,j) */ for (p = Cp [j] ; p < cnz ; p++) { i = Ci [p] ; Cx [p] = W [i] ; W [i] = 0 ; } } } else { /* pattern only */ for (j = 0 ; j < ncol ; j++) { /* clear the Flag array */ /* mark = CHOLMOD(clear_flag) (Common) ; */ CHOLMOD_CLEAR_FLAG (Common) ; mark = Common->mark ; /* start column j of C */ Cp [j] = cnz ; /* for each nonzero B(t,j) in column j, do: */ pb = Bp [j] ; pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ; for ( ; pb < pbend ; pb++) { /* B(t,j) is nonzero */ t = Bi [pb] ; /* add the nonzero pattern of A(:,t) to the pattern of C(:,j) */ pa = Ap [t] ; paend = (apacked) ? (Ap [t+1]) : (pa + Anz [t]) ; for ( ; pa < paend ; pa++) { i = Ai [pa] ; if (Flag [i] != mark) { Flag [i] = mark ; Ci [cnz++] = i ; } } } } } Cp [ncol] = cnz ; ASSERT (MAX (1,cnz) == C->nzmax) ; /* ---------------------------------------------------------------------- */ /* clear workspace and free temporary matrices */ /* ---------------------------------------------------------------------- */ CHOLMOD(free_sparse) (&A2, Common) ; CHOLMOD(free_sparse) (&B2, Common) ; /* CHOLMOD(clear_flag) (Common) ; */ CHOLMOD_CLEAR_FLAG (Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; /* ---------------------------------------------------------------------- */ /* convert C to a symmetric upper/lower matrix if requested */ /* ---------------------------------------------------------------------- */ /* convert C in place, which cannot fail since no memory is allocated */ if (stype > 0) { /* C = triu (C), in place */ (void) CHOLMOD(band_inplace) (0, ncol, values, C, Common) ; C->stype = 1 ; } else if (stype < 0) { /* C = tril (C), in place */ (void) CHOLMOD(band_inplace) (-nrow, 0, values, C, Common) ; C->stype = -1 ; } ASSERT (Common->status >= CHOLMOD_OK) ; /* ---------------------------------------------------------------------- */ /* sort C, if requested */ /* ---------------------------------------------------------------------- */ if (sorted) { if (do_swap_and_transpose) { /* workspace: Iwork (C->ncol), which is A->nrow since C=(B'*A') */ C2 = CHOLMOD(ptranspose) (C, values, NULL, NULL, 0, Common) ; CHOLMOD(free_sparse) (&C, Common) ; if (Common->status < CHOLMOD_OK) { /* out of memory */ ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)); return (NULL) ; } C = C2 ; } else { /* workspace: Iwork (max (C->nrow,C->ncol)) */ if (!CHOLMOD(sort) (C, Common)) { /* out of memory */ CHOLMOD(free_sparse) (&C, Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)); return (NULL) ; } } } /* ---------------------------------------------------------------------- */ /* return result */ /* ---------------------------------------------------------------------- */ DEBUG (CHOLMOD(dump_sparse) (C, "ssmult", Common) >= 0) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n1:0, Common)) ; return (C) ; }
/* * 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; } }
int main( int argc, char** argv ){ FILE *ifp; gray maxval; int cols, rows, format; gray* prevrow; gray* thisrow; gray* tmprow; int* countTile; int* countEdgeX; int* countEdgeY; int* countVertex; int i, col, row; int maxtiles, maxedgex, maxedgey, maxvertex; int area, perimeter, eulerchi; double l2inv, linv; /* * parse arg and initialize */ pgm_init( &argc, argv ); if ( argc > 2 ) pm_usage( "[pgmfile]" ); if ( argc == 2 ) ifp = pm_openr( argv[1] ); else ifp = stdin; /* * initialize */ pgm_readpgminit( ifp, &cols, &rows, &maxval, &format ); prevrow = pgm_allocrow( cols ); thisrow = pgm_allocrow( cols ); MALLOCARRAY(countTile , maxval + 1 ); MALLOCARRAY(countEdgeX , maxval + 1 ); MALLOCARRAY(countEdgeY , maxval + 1 ); MALLOCARRAY(countVertex , maxval + 1 ); if (countTile == NULL || countEdgeX == NULL || countEdgeY == NULL || countVertex == NULL) pm_error( "out of memory" ); for ( i = 0; i <= maxval; i++ ) countTile[i] = 0; for ( i = 0; i <= maxval; i++ ) countEdgeX[i] = 0; for ( i = 0; i <= maxval; i++ ) countEdgeY[i] = 0; for ( i = 0; i <= maxval; i++ ) countVertex[i] = 0; /* first row */ pgm_readpgmrow( ifp, thisrow, cols, maxval, format ); /* tiles */ for ( col = 0; col < cols; ++col ) ++countTile[thisrow[col]]; /* y-edges */ for ( col = 0; col < cols; ++col ) ++countEdgeY[thisrow[col]]; /* x-edges */ ++countEdgeX[thisrow[0]]; for ( col = 0; col < cols-1; ++col ) ++countEdgeX[ MAX2(thisrow[col], thisrow[col+1]) ]; ++countEdgeX[thisrow[cols-1]]; /* shortcut: for the first row, countVertex == countEdgeX */ ++countVertex[thisrow[0]]; for ( col = 0; col < cols-1; ++col ) ++countVertex[ MAX2(thisrow[col], thisrow[col+1]) ]; ++countVertex[thisrow[cols-1]]; for ( row = 1; row < rows; ++row ){ tmprow = prevrow; prevrow = thisrow; thisrow = tmprow; pgm_readpgmrow( ifp, thisrow, cols, maxval, format ); /* tiles */ for ( col = 0; col < cols; ++col ) ++countTile[thisrow[col]]; /* y-edges */ for ( col = 0; col < cols; ++col ) ++countEdgeY[ MAX2(thisrow[col], prevrow[col]) ]; /* x-edges */ ++countEdgeX[thisrow[0]]; for ( col = 0; col < cols-1; ++col ) ++countEdgeX[ MAX2(thisrow[col], thisrow[col+1]) ]; ++countEdgeX[thisrow[cols-1]]; /* vertices */ ++countVertex[ MAX2(thisrow[0],prevrow[0]) ]; for ( col = 0; col < cols-1; ++col ) ++countVertex[ MAX4(thisrow[col], thisrow[col+1], prevrow[col], prevrow[col+1]) ]; ++countVertex[ MAX2(thisrow[cols-1],prevrow[cols-1]) ]; } /* for row */ /* now thisrow contains the top row*/ /* tiles and x-edges have been counted, now upper y-edges and top vertices remain */ /* y-edges */ for ( col = 0; col < cols; ++col ) ++countEdgeY[ thisrow[col] ]; /* vertices */ ++countVertex[thisrow[0]]; for ( col = 0; col < cols-1; ++col ) ++countVertex[ MAX2(thisrow[col],thisrow[col+1]) ]; ++countVertex[ thisrow[cols-1] ]; /* cleanup */ maxtiles = rows * cols; maxedgex = rows * (cols+1); maxedgey = (rows+1) * cols; maxvertex= (rows+1) * (cols+1); l2inv = 1.0/maxtiles; linv = 0.5/(rows+cols); /* And print it. */ printf( "#threshold\t tiles\tx-edges\ty-edges\tvertices\n" ); printf( "#---------\t -----\t-------\t-------\t--------\n" ); for ( i = 0; i <= maxval; i++ ){ if( !(countTile[i] || countEdgeX[i] || countEdgeY[i] || countVertex[i] ) ) continue; /* skip empty slots */ area = maxtiles; perimeter = 2*maxedgex + 2*maxedgey - 4*maxtiles; eulerchi = maxtiles - maxedgex - maxedgey + maxvertex; printf( "%f\t%6d\t%7d\t%7d\t%8d\t%g\t%g\t%6d\n", (float) i/(1.0*maxval), maxtiles, maxedgex, maxedgey, maxvertex, area*l2inv, perimeter*linv, eulerchi ); maxtiles -= countTile[i]; maxedgex -= countEdgeX[i]; maxedgey -= countEdgeY[i]; maxvertex-= countVertex[i]; /* i, countTile[i], countEdgeX[i], countEdgeY[i], countVertex[i] */ } /* these should be zero: */ printf( "# check:\t%6d\t%7d\t%7d\t%8d\n", maxtiles, maxedgex, maxedgey, maxvertex ); pm_close( ifp ); exit( 0 ); } /*main*/