SUMOReal
MSCFModel_Kerner::_v(const MSVehicle* const veh, SUMOReal speed, SUMOReal vfree, SUMOReal gap, SUMOReal predSpeed) const {
    if (predSpeed == 0 && gap < 0.01) {
        return 0;
    }
    // !!! in the following, the prior step is not considered!!!
    SUMOReal G = MAX2((SUMOReal) 0, (SUMOReal)(SPEED2DIST(myK * speed) + myPhi / myAccel * speed * (speed - predSpeed)));
    SUMOReal vcond = gap > G ? speed + ACCEL2SPEED(myAccel) : speed + MAX2(ACCEL2SPEED(-myDecel), MIN2(ACCEL2SPEED(myAccel), predSpeed - speed));
    SUMOReal vsafe = (SUMOReal)(-1. * myTauDecel + sqrt(myTauDecel * myTauDecel + (predSpeed * predSpeed) + (2. * myDecel * gap)));
    VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
    SUMOReal va = MAX2((SUMOReal) 0, MIN3(vfree, vsafe, vcond)) + vars->rand;
    SUMOReal v = MAX2((SUMOReal) 0, MIN4(vfree, va, speed + ACCEL2SPEED(myAccel), vsafe));
    return v;
}
Example #2
0
void
gimp_display_shell_rotate_untransform_bounds (GimpDisplayShell *shell,
                                              gdouble           x1,
                                              gdouble           y1,
                                              gdouble           x2,
                                              gdouble           y2,
                                              gdouble          *nx1,
                                              gdouble          *ny1,
                                              gdouble          *nx2,
                                              gdouble          *ny2)
{
  gdouble tx1, ty1;
  gdouble tx2, ty2;
  gdouble tx3, ty3;
  gdouble tx4, ty4;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));

  tx1 = x1;
  ty1 = y1;
  tx2 = x1;
  ty2 = y2;
  tx3 = x2;
  ty3 = y1;
  tx4 = x2;
  ty4 = y2;

  cairo_matrix_transform_point (shell->rotate_untransform, &tx1, &ty1);
  cairo_matrix_transform_point (shell->rotate_untransform, &tx2, &ty2);
  cairo_matrix_transform_point (shell->rotate_untransform, &tx3, &ty3);
  cairo_matrix_transform_point (shell->rotate_untransform, &tx4, &ty4);

  *nx1 = MIN4 (tx1, tx2, tx3, tx4);
  *ny1 = MIN4 (ty1, ty2, ty3, ty4);
  *nx2 = MAX4 (tx1, tx2, tx3, tx4);
  *ny2 = MAX4 (ty1, ty2, ty3, ty4);
}
Example #3
0
static void
get_bounding_box (GtkWidget    *widget,
                  GdkRectangle *bounds)
{
  GtkAllocation allocation;
  GdkWindow *window;
  gint x, y;
  gint w, h;
  gint x1, y1;
  gint x2, y2;
  gint x3, y3;
  gint x4, y4;

  window = gtk_widget_get_parent_window (widget);
  if (window == NULL)
    window = gtk_widget_get_window (widget);

  gtk_widget_get_allocation (widget, &allocation);
  x = allocation.x;
  y = allocation.y;
  w = allocation.width;
  h = allocation.height;

  gdk_window_get_root_coords (window, x, y, &x1, &y1);
  gdk_window_get_root_coords (window, x + w, y, &x2, &y2);
  gdk_window_get_root_coords (window, x, y + h, &x3, &y3);
  gdk_window_get_root_coords (window, x + w, y + h, &x4, &y4);

#define MIN4(a,b,c,d) MIN(MIN(a,b),MIN(c,d))
#define MAX4(a,b,c,d) MAX(MAX(a,b),MAX(c,d))

  bounds->x = floor (MIN4 (x1, x2, x3, x4));
  bounds->y = floor (MIN4 (y1, y2, y3, y4));
  bounds->width = ceil (MAX4 (x1, x2, x3, x4)) - bounds->x;
  bounds->height = ceil (MAX4 (y1, y2, y3, y4)) - bounds->y;
}
SUMOReal
MSCFModel_KraussOrig1::moveHelper(MSVehicle * const veh, const MSLane * const lane, SUMOReal vPos) const throw() {
    SUMOReal oldV = veh->getSpeed(); // save old v for optional acceleration computation
    SUMOReal vSafe = MIN2(vPos, veh->processNextStop(vPos)); // process stops
    // we need the acceleration for emission computation;
    //  in this case, we neglect dawdling, nonetheless, using
    //  vSafe does not incorporate speed reduction due to interaction
    //  on lane changing
    veh->setPreDawdleAcceleration(SPEED2ACCEL(vSafe-oldV));
    //
    SUMOReal vNext = dawdle(MIN3(lane->getMaxSpeed(), maxNextSpeed(oldV), vSafe));
    vNext =
        veh->getLaneChangeModel().patchSpeed(
            MAX2((SUMOReal) 0, oldV-(SUMOReal)ACCEL2SPEED(myDecel)), //!!! reverify
            vNext,
            MIN3(vSafe, veh->getLane().getMaxSpeed(), maxNextSpeed(oldV)),//vaccel(myState.mySpeed, myLane->maxSpeed())),
            vSafe);
    return MIN4(vNext, vSafe, veh->getLane().getMaxSpeed(), maxNextSpeed(oldV));
}
Example #5
0
int compute_dequeue_size (buf_t *buf, int request_size)
{
  int next_action_pos;

  /* 
     For simplicity, the number of bytes played must satisfy the following
     requirements:
     1. Do not extract more bytes than are stored in the buffer.
     2. Do not extract more bytes than the requested number of bytes.
     3. Do not run off the end of the buffer.
     4. Do not go past the next action.
  */

  if (buf->actions != NULL) {

    next_action_pos = buf->actions->position;
    
    return MIN4(buf->curfill, request_size,
		buf->size - buf->start, next_action_pos - buf->position);
  } else
    return MIN3(buf->curfill, request_size, buf->size - buf->start);

}
Example #6
0
/* 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;
}
Example #7
0
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;
}
Example #9
0
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;
		}
	}
Example #10
0
static void trace_draw2filled(DNATrace *t, Display *d, Pixmap p, int max,
			int x0, int xn, int height, double ys,
			int off) {
    int i, h = height-1, o;
    XPoint *xp[4], *xp2[4];
    GC gc[4];
    TRACE *tr[4];
    int ch;

    gc[0] = t->Agc;
    gc[1] = t->Cgc;
    gc[2] = t->Ggc;
    gc[3] = t->Tgc;

    tr[0] = &t->read->traceA[x0];
    tr[1] = &t->read->traceC[x0];
    tr[2] = &t->read->traceG[x0];
    tr[3] = &t->read->traceT[x0];

    for (ch = 0; ch < 4; ch++) {
	if (NULL == (xp[ch] = (XPoint *)xmalloc((xn+2) * sizeof(XPoint)))) {
	    return;
	}
	xp[ch]++;
    }

    o = t->disp_offset * t->scale_x;

    if (t->read->maxTraceVal)
	h -= h*(double)off/t->read->maxTraceVal;
    for (ch = 0; ch < 4; ch++) {
	TRACE *trp = tr[ch];
	XPoint *xpp = xp[ch];
	for (i = 0; i < xn; i++, trp++) {
	    xpp[i].x = (int)((x0 + i) * t->scale_x) - o;
	    xpp[i].y = h - ys * (*trp-off);
	}
	tr[ch] = trp;
    }

    /* Clip off negative X coordinates as this crashes Linux X servers */
    for (i = 0; i < xn; i++) {
	if (xp[0][i].x >= 0 &&
	    xp[1][i].x >= 0 &&
	    xp[2][i].x >= 0 &&
	    xp[3][i].x >= 0)
	    break;
    }
    xp2[0] = &xp[0][i];
    xp2[1] = &xp[1][i];
    xp2[2] = &xp[2][i];
    xp2[3] = &xp[3][i];
    xn -= i;

#if 1
    /* Draw first peak as a line and all lower ones as solid */
    {
	int cur_max;
	int start = 0;

	i = 1;
	cur_max = MIN4(xp2,0);

	do {
	    while (MIN4(xp2,i) == cur_max && i < xn)
		i++;

	    for (ch = 0; ch < 4; ch++) {
		if (ch == cur_max) {
		    XDrawLines(d, p, gc[ch], &xp2[ch][start], i-start,
			       CoordModeOrigin);
		} else {
		    XPoint tmp;
		    tmp = xp2[ch][i];
		    xp2[ch][start-1].x = xp2[ch][start].x;
		    xp2[ch][start-1].y = h;
		    xp2[ch][i].x = xp2[ch][i-1].x;
		    xp2[ch][i].y = h;
		    XFillPolygon(d, p, gc[ch], &xp2[ch][start-1], i-start+2,
				 Nonconvex, CoordModeOrigin);
		    xp2[ch][i] = tmp;
		}
	    }
	    start = i;
	    cur_max = MIN4(xp2,i);
	} while (i < xn);
    }
#endif

#if 0
    /* Draw all peaks as solid */
    for (ch = 0; ch < 4; ch++) {
	/*
	XDrawLines(d, p, gc[ch], xp2[ch], xn,
		   CoordModeOrigin);
	*/
	xp2[ch][0].y = h;
	xp2[ch][xn-1].y = h;
	XFillPolygon(d, p, gc[ch], xp2[ch], xn,
		     Nonconvex, CoordModeOrigin);
    }
#endif

    for (ch = 0; ch < 4; ch++) {
	xp[ch]--;
	xfree(xp[ch]);
    }
}
Example #11
0
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);
}
Example #12
0
int calculate(int len, int nThreads) { 
	int b, i, j;
#ifdef _OPENMP
	if (nThreads>0) omp_set_num_threads(nThreads);
#endif
#ifdef _OPENMP
#pragma omp parallel
#pragma omp master
	fprintf(stdout,"Thread count: %3d \n",omp_get_num_threads());
#endif


	for (b = TURN+1; b <= len-1; b++) {
#ifdef _OPENMP
#pragma omp parallel for private (i,j) schedule(guided)
#endif
		for (i = 1; i <= len - b; i++) {
			j = i + b;
			int flag = 0, newWM = INFINITY_; 
			if (canPair(RNA[i], RNA[j])) {
				flag = 1;
				int eh = canHairpin(i,j)?eH(i,j):INFINITY_; //hair pin
				int es = canStack(i,j)?eS(i,j)+getShapeEnergy(i)+getShapeEnergy(j)+V(i+1,j-1):INFINITY_; // stack
				if (j-i > 6) { // Internal Loop BEGIN
					int p=0, q=0;
					int VBIij = INFINITY_;
					for (p = i+1; p <= MIN(j-2-TURN,i+MAXLOOP+1) ; p++) {
						int minq = j-i+p-MAXLOOP-2;
						if (minq < p+1+TURN) minq = p+1+TURN;
						int maxq = (p==i+1)?(j-2):(j-1);
						for (q = minq; q <= maxq; q++) {
							if (!canPair(RNA[p], RNA[q])) continue;
							if (!canILoop(i,j,p,q)) continue;
							VBIij = MIN(eL(i, j, p, q) + V(p,q), VBIij);
						}
					}
					VBI(i,j) = VBIij;
					V(i,j) = V(i,j) + getShapeEnergy(i) + getShapeEnergy(j);

				} // Internal Loop END
				if (j-i > 10) { // Multi Loop BEGIN
					int h;
					int VMij, VMijd, VMidj, VMidjd;
					VMij = VMijd = VMidj = VMidjd = INFINITY_;
					for (h = i+TURN+1; h <= j-1-TURN; h++) { 
						VMij = MIN(VMij, WMU(i+1,h-1) + WML(h,j-1)); 
						VMidj = MIN(VMidj, WMU(i+2,h-1) + WML(h,j-1)); 
						VMijd = MIN(VMijd, WMU(i+1,h-1) + WML(h,j-2)); 
						VMidjd = MIN(VMidjd, WMU(i+2,h-1) + WML(h,j-2)); 
					}
					int d3 = canSS(j-1)?Ed3(i,j,j-1):INFINITY_;
					int d5 = canSS(i+1)?Ed5(i,j,i+1):INFINITY_;
					VMij = MIN(VMij, (VMidj + d5 +Ec)) ;
					VMij = MIN(VMij, (VMijd + d3 +Ec));
					VMij = MIN(VMij, (VMidjd + d5 + d3+ 2*Ec));
					VMij = VMij + Ea + Eb + auPenalty(i,j);
					VM(i,j) = canStack(i,j)?VMij:INFINITY_;
				} // Multi Loop END
				V(i,j) = MIN4(eh,es,VBI(i,j),VM(i,j));
			}
			else V(i,j) = INFINITY_;
			if (j-i > 4) { // WM BEGIN
				int h; 
				for (h = i+TURN+1 ; h <= j-TURN-1; h++) {
					//ZS: This sum corresponds to when i,j are NOT paired with each other.
					//So we need to make sure only terms where i,j aren't pairing are considered. 
					newWM = (!forcePair(i,j))?MIN(newWM, WMU(i,h-1) + WML(h,j)):newWM;
				}
				newWM = MIN(V(i,j) + auPenalty(i,j) + Eb, newWM); 
				newWM = canSS(i)?MIN(V(i+1,j) + Ed3(j,i+1,i) + auPenalty(i+1,j) + Eb + Ec, newWM):newWM; //i dangle
				newWM = canSS(j)?MIN(V(i,j-1) + Ed5(j-1,i,j) + auPenalty(i,j-1) + Eb + Ec, newWM):newWM;  //j dangle
				newWM = (canSS(i)&&canSS(j))?MIN(V(i+1,j-1) + Ed3(j-1,i+1,i) + Ed5(j-1,i+1,j) + auPenalty(i+1,j-1) + Eb + 2*Ec, newWM):newWM; //i,j dangle
				newWM = canSS(i)?MIN(WMU(i+1,j) + Ec, newWM):newWM; //i dangle
				newWM = canSS(j)?MIN(WML(i,j-1) + Ec, newWM):newWM; //j dangle
				WMU(i,j) = WML(i,j) = newWM;
			} // WM END
		}
	}
	for (j = TURN+2; j <= len; j++) {
		int i, Wj, Widjd, Wijd, Widj, Wij, Wim1;
		Wj = INFINITY_;
		for (i = 1; i < j-TURN; i++) {
			Wij = Widjd = Wijd = Widj = INFINITY_;
			Wim1 = MIN(0, W[i-1]); 
			Wij = V(i, j) + auPenalty(i, j) + Wim1;
			Widjd = (canSS(i)&&canSS(j))?V(i+1,j-1) + auPenalty(i+1,j-1) + Ed3(j-1,i + 1,i) + Ed5(j-1,i+1,j) + Wim1:Widjd;
			Wijd = canSS(j)?V(i,j-1) + auPenalty(i,j-1) + Ed5(j-1,i,j) + Wim1:Wijd;
			Widj = canSS(i)?V(i+1, j) + auPenalty(i+1,j) + Ed3(j,i + 1,i) + Wim1:Widj;
			Wj = MIN(MIN4(Wij, Widjd, Wijd, Widj), Wj); 
		}
		W[j] = canSS(j)?MIN(Wj, W[j-1]):Wj;
	}
	return W[len];
}
/* this takes the smallest ortho-aligned (the sides of the rectangle are
 * parallel to the x- and y-axis) rectangle fitting around the points a to d,
 * checks if the whole rectangle is inside the polygon described by points and
 * writes it to r if the area is bigger than the rectangle already stored in r.
 */
static void
add_rectangle (Point      points[4],
               Rectangle *r,
               Point      a,
               Point      b,
               Point      c,
               Point      d)
{
  gdouble width;
  gdouble height;
  gdouble minx, maxx;
  gdouble miny, maxy;

  /* get the orthoaligned (the sides of the rectangle are parallel to the x-
   * and y-axis) rectangle surrounding the points a to d.
   */
  minx = MIN4 (a.x, b.x, c.x, d.x);
  maxx = MAX4 (a.x, b.x, c.x, d.x);
  miny = MIN4 (a.y, b.y, c.y, d.y);
  maxy = MAX4 (a.y, b.y, c.y, d.y);

  a.x = minx;
  a.y = miny;

  b.x = maxx;
  b.y = miny;

  c.x = maxx;
  c.y = maxy;

  d.x = minx;
  d.y = maxy;

  width  =  maxx - minx;
  height =  maxy - miny;

  /* check if this rectangle is inside the polygon "points" */
  if (in_poly (points, a) &&
      in_poly (points, b) &&
      in_poly (points, c) &&
      in_poly (points, d))
    {
      gdouble area = width * height;

      /* check if the new rectangle is larger (in terms of area)
       * than the currently stored rectangle in r, if yes store
       * new rectangle to r
       */
      if (r->area <= area)
        {
          r->a.x = a.x;
          r->a.y = a.y;

          r->b.x = b.x;
          r->b.y = b.y;

          r->c.x = c.x;
          r->c.y = c.y;

          r->d.x = d.x;
          r->d.y = d.y;

          r->area = area;
        }
    }
}
Example #14
0
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;
}
Example #15
0
/*
 * 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;
}
Example #16
0
/*
 * 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;
    }
}
Example #17
0
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;
}