1 #if defined(HAVE_CONFIG_H)
6 #define GL_GLEXT_PROTOTYPES
20 AffineMatrix::AffineMatrix()
22 bzero(values, sizeof(values));
25 void AffineMatrix::identity()
27 bzero(values, sizeof(values));
33 void AffineMatrix::translate(double x, double y)
35 double g = values[2][0];
36 double h = values[2][1];
37 double i = values[2][2];
38 values[0][0] += x * g;
39 values[0][1] += x * h;
40 values[0][2] += x * i;
41 values[1][0] += y * g;
42 values[1][1] += y * h;
43 values[1][2] += y * i;
46 void AffineMatrix::scale(double x, double y)
57 void AffineMatrix::multiply(AffineMatrix *dst)
63 for (i = 0; i < 3; i++)
68 for (j = 0; j < 3; j++)
70 tmp.values[i][j] = t1 * dst->values[0][j];
71 tmp.values[i][j] += t2 * dst->values[1][j];
72 tmp.values[i][j] += t3 * dst->values[2][j];
78 double AffineMatrix::determinant()
83 values[0][0] * (values[1][1] * values[2][2] - values[1][2] * values[2][1]);
85 values[1][0] * (values[0][1] * values[2][2] - values[0][2] * values[2][1]);
87 values[2][0] * (values[0][1] * values[1][2] - values[0][2] * values[1][1]);
92 void AffineMatrix::invert(AffineMatrix *dst)
96 det_1 = determinant();
104 (values[1][1] * values[2][2] - values[1][2] * values[2][1]) * det_1;
107 - (values[1][0] * values[2][2] - values[1][2] * values[2][0]) * det_1;
110 (values[1][0] * values[2][1] - values[1][1] * values[2][0]) * det_1;
113 - (values[0][1] * values[2][2] - values[0][2] * values[2][1] ) * det_1;
116 (values[0][0] * values[2][2] - values[0][2] * values[2][0]) * det_1;
119 - (values[0][0] * values[2][1] - values[0][1] * values[2][0]) * det_1;
122 (values[0][1] * values[1][2] - values[0][2] * values[1][1]) * det_1;
125 - (values[0][0] * values[1][2] - values[0][2] * values[1][0]) * det_1;
128 (values[0][0] * values[1][1] - values[0][1] * values[1][0]) * det_1;
131 void AffineMatrix::copy_from(AffineMatrix *src)
133 memcpy(&values[0][0], &src->values[0][0], sizeof(values));
136 void AffineMatrix::transform_point(float x,
143 w = values[2][0] * x + values[2][1] * y + values[2][2];
150 *newx = (values[0][0] * x + values[0][1] * y + values[0][2]) * w;
151 *newy = (values[1][0] * x + values[1][1] * y + values[1][2]) * w;
154 void AffineMatrix::dump()
156 printf("AffineMatrix::dump\n");
157 printf("%f %f %f\n", values[0][0], values[0][1], values[0][2]);
158 printf("%f %f %f\n", values[1][0], values[1][1], values[1][2]);
159 printf("%f %f %f\n", values[2][0], values[2][1], values[2][2]);
166 AffinePackage::AffinePackage()
174 AffineUnit::AffineUnit(AffineEngine *server)
177 this->server = server;
188 void AffineUnit::calculate_matrix(
201 AffineMatrix *result)
207 scalex = scaley = 1.0;
209 if((in_x2 - in_x1) > 0)
210 scalex = 1.0 / (double)(in_x2 - in_x1);
212 if((in_y2 - in_y1) > 0)
213 scaley = 1.0 / (double)(in_y2 - in_y1);
215 /* Determine the perspective transform that maps from
216 * the unit cube to the transformed coordinates
218 double dx1, dx2, dx3, dy1, dy2, dy3;
221 dx1 = out_x2 - out_x4;
222 dx2 = out_x3 - out_x4;
223 dx3 = out_x1 - out_x2 + out_x4 - out_x3;
225 dy1 = out_y2 - out_y4;
226 dy2 = out_y3 - out_y4;
227 dy3 = out_y1 - out_y2 + out_y4 - out_y3;
228 // printf("AffineUnit::calculate_matrix %f %f %f %f %f %f\n",
237 /* Is the mapping affine? */
238 if((dx3 == 0.0) && (dy3 == 0.0))
240 matrix.values[0][0] = out_x2 - out_x1;
241 matrix.values[0][1] = out_x4 - out_x2;
242 matrix.values[0][2] = out_x1;
243 matrix.values[1][0] = out_y2 - out_y1;
244 matrix.values[1][1] = out_y4 - out_y2;
245 matrix.values[1][2] = out_y1;
246 matrix.values[2][0] = 0.0;
247 matrix.values[2][1] = 0.0;
251 det1 = dx3 * dy2 - dy3 * dx2;
252 det2 = dx1 * dy2 - dy1 * dx2;
253 matrix.values[2][0] = det1 / det2;
254 det1 = dx1 * dy3 - dy1 * dx3;
255 det2 = dx1 * dy2 - dy1 * dx2;
256 matrix.values[2][1] = det1 / det2;
258 matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2;
259 matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3;
260 matrix.values[0][2] = out_x1;
262 matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2;
263 matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3;
264 matrix.values[1][2] = out_y1;
267 matrix.values[2][2] = 1.0;
269 // printf("AffineUnit::calculate_matrix 1 %f %f\n", dx3, dy3);
273 result->translate(-in_x1, -in_y1);
274 result->scale(scalex, scaley);
275 matrix.multiply(result);
276 // double test[3][3] = { { 0.0896, 0.0, 0.0 },
277 // { 0.0, 0.0896, 0.0 },
278 // { -0.00126, 0.0, 1.0 } };
279 // memcpy(&result->values[0][0], test, sizeof(test));
280 // printf("AffineUnit::calculate_matrix 4 %p\n", result);
286 float AffineUnit::transform_cubic(float dx,
292 /* Catmull-Rom - not bad */
293 float result = ((( ( - jm1 + 3.0 * j - 3.0 * jp1 + jp2 ) * dx +
294 ( 2.0 * jm1 - 5.0 * j + 4.0 * jp1 - jp2 ) ) * dx +
295 ( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0;
296 // printf("%f %f %f %f %f\n",
308 void AffineUnit::process_package(LoadPackage *package)
310 AffinePackage *pkg = (AffinePackage*)package;
311 int minx = server->x;
312 int miny = server->y;
313 int maxx = server->x + server->w - 1;
314 int maxy = server->y + server->h - 1;
316 // Calculate real coords
317 float out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4;
318 if(server->mode == AffineEngine::STRETCH ||
319 server->mode == AffineEngine::PERSPECTIVE ||
320 server->mode == AffineEngine::ROTATE)
322 out_x1 = (float)server->x + (float)server->x1 * server->w / 100;
323 out_y1 = (float)server->y + (float)server->y1 * server->h / 100;
324 out_x2 = (float)server->x + (float)server->x2 * server->w / 100;
325 out_y2 = (float)server->y + (float)server->y2 * server->h / 100;
326 out_x3 = (float)server->x + (float)server->x3 * server->w / 100;
327 out_y3 = (float)server->y + (float)server->y3 * server->h / 100;
328 out_x4 = (float)server->x + (float)server->x4 * server->w / 100;
329 out_y4 = (float)server->y + (float)server->y4 * server->h / 100;
333 out_x1 = (float)server->x + (float)server->x1 * server->w / 100;
335 out_x2 = out_x1 + server->w;
337 out_x4 = (float)server->x + (float)server->x4 * server->w / 100;
338 out_y4 = server->y + server->h;
339 out_x3 = out_x4 + server->w;
340 out_y3 = server->y + server->h;
345 // Rotation with OpenGL uses a simple quad.
346 if(server->mode == AffineEngine::ROTATE &&
350 server->output->to_texture();
351 server->output->enable_opengl();
352 server->output->init_screen();
353 server->output->bind_texture(0);
354 server->output->clear_pbuffer();
356 int texture_w = server->output->get_texture_w();
357 int texture_h = server->output->get_texture_h();
358 float output_h = server->output->get_h();
359 float in_x1 = (float)server->x / texture_w;
360 float in_x2 = (float)(server->x + server->w) / texture_w;
361 float in_y1 = (float)server->y / texture_h;
362 float in_y2 = (float)(server->y + server->h) / texture_h;
364 // printf("%f %f %f %f\n%f,%f %f,%f %f,%f %f,%f\n", in_x1, in_y1, in_x2, in_y2,
365 // out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4);
368 glNormal3f(0, 0, 1.0);
370 glTexCoord2f(in_x1, in_y1);
371 glVertex3f(out_x1, -output_h+out_y1, 0);
373 glTexCoord2f(in_x2, in_y1);
374 glVertex3f(out_x2, -output_h+out_y2, 0);
376 glTexCoord2f(in_x2, in_y2);
377 glVertex3f(out_x3, -output_h+out_y3, 0);
379 glTexCoord2f(in_x1, in_y2);
380 glVertex3f(out_x4, -output_h+out_y4, 0);
385 server->output->set_opengl_state(VFrame::SCREEN);
389 if(server->mode == AffineEngine::PERSPECTIVE ||
390 server->mode == AffineEngine::SHEER ||
391 server->mode == AffineEngine::ROTATE)
410 server->x + server->w,
411 server->y + server->h,
422 // printf("AffineUnit::process_package 10 %f %f %f %f %f %f %f %f\n",
432 int reverse = !server->forward;
434 float xinc, yinc, winc;
438 int tx1, ty1, tx2, ty2;
442 m.copy_from(&matrix);
444 matrix.copy_from(&im);
455 matrix.transform_point(server->x, server->y, &dx1, &dy1);
456 matrix.transform_point(server->x + server->w, server->y, &dx2, &dy2);
457 matrix.transform_point(server->x, server->y + server->h, &dx3, &dy3);
458 matrix.transform_point(server->x + server->w, server->y + server->h, &dx4, &dy4);
460 //printf("AffineUnit::process_package 1 y1=%d y2=%d\n", pkg->y1, pkg->y2);
461 //printf("AffineUnit::process_package 1 %f %f %f %f\n", dy1, dy2, dy3, dy4);
462 //printf("AffineUnit::process_package 2 %d ty1=%d %d ty2=%d %f %f\n", tx1, ty1, tx2, ty2, out_x4, out_y4);
465 if(server->use_opengl)
468 static char *affine_frag =
469 "uniform sampler2D tex;\n"
470 "uniform mat3 affine_matrix;\n"
471 "uniform vec2 texture_extents;\n"
472 "uniform vec2 image_extents;\n"
473 "uniform vec4 border_color;\n"
476 " vec2 outcoord = gl_TexCoord[0].st;\n"
477 " outcoord *= texture_extents;\n"
478 " mat3 coord_matrix = mat3(\n"
479 " outcoord.x, outcoord.y, 1.0, \n"
480 " outcoord.x, outcoord.y, 1.0, \n"
481 " outcoord.x, outcoord.y, 1.0);\n"
482 " mat3 incoord_matrix = affine_matrix * coord_matrix;\n"
483 " vec2 incoord = vec2(incoord_matrix[0][0], incoord_matrix[0][1]);\n"
484 " incoord /= incoord_matrix[0][2];\n"
485 " incoord /= texture_extents;\n"
486 " if(incoord.x > image_extents.x || incoord.y > image_extents.y)\n"
487 " gl_FragColor = border_color;\n"
489 " gl_FragColor = texture2D(tex, incoord);\n"
492 float affine_matrix[9] = {
493 m.values[0][0], m.values[1][0], m.values[2][0],
494 m.values[0][1], m.values[1][1], m.values[2][1],
495 m.values[0][2], m.values[1][2], m.values[2][2]
499 server->output->to_texture();
500 server->output->enable_opengl();
501 unsigned int frag_shader = VFrame::make_shader(0,
506 glUseProgram(frag_shader);
507 glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
508 glUniformMatrix3fv(glGetUniformLocation(frag_shader, "affine_matrix"),
512 glUniform2f(glGetUniformLocation(frag_shader, "texture_extents"),
513 (GLfloat)server->output->get_texture_w(),
514 (GLfloat)server->output->get_texture_h());
515 glUniform2f(glGetUniformLocation(frag_shader, "image_extents"),
516 (GLfloat)server->output->get_w() / server->output->get_texture_w(),
517 (GLfloat)server->output->get_h() / server->output->get_texture_h());
518 float border_color[] = { 0, 0, 0, 0 };
519 if(cmodel_is_yuv(server->output->get_color_model()))
521 border_color[1] = 0.5;
522 border_color[2] = 0.5;
524 glUniform4fv(glGetUniformLocation(frag_shader, "border_color"),
526 (GLfloat*)border_color);
527 server->output->init_screen();
528 server->output->bind_texture(0);
529 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
532 server->output->draw_texture();
534 server->output->set_opengl_state(VFrame::SCREEN);
545 #define ROUND(x) ((int)((x > 0) ? (x) + 0.5 : (x) - 0.5))
546 #define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d)
547 #define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d)
549 tx1 = ROUND(MIN4(dx1, dx2, dx3, dx4));
550 ty1 = ROUND(MIN4(dy1, dy2, dy3, dy4));
552 tx2 = ROUND(MAX4(dx1, dx2, dx3, dx4));
553 ty2 = ROUND(MAX4(dy1, dy2, dy3, dy4));
555 CLAMP(ty1, pkg->y1, pkg->y2);
556 CLAMP(ty2, pkg->y1, pkg->y2);
558 xinc = m.values[0][0];
559 yinc = m.values[1][0];
560 winc = m.values[2][0];
563 #define CUBIC_ROW(in_row, chroma_offset) \
564 transform_cubic(dx, \
565 in_row[col1_offset] - chroma_offset, \
566 in_row[col2_offset] - chroma_offset, \
567 in_row[col3_offset] - chroma_offset, \
568 in_row[col4_offset] - chroma_offset)
570 #define TRANSFORM(components, type, temp_type, chroma_offset, max) \
572 type **in_rows = (type**)server->input->get_rows(); \
573 float round_factor = 0.0; \
574 if(sizeof(type) < 4) round_factor = 0.5; \
575 for(int y = ty1; y < ty2; y++) \
577 type *out_row = (type*)server->output->get_rows()[y]; \
581 tx = xinc * (tx1 + 0.5) + m.values[0][1] * (y + 0.5) + m.values[0][2]; \
582 ty = yinc * (tx1 + 0.5) + m.values[1][1] * (y + 0.5) + m.values[1][2]; \
583 tw = winc * (tx1 + 0.5) + m.values[2][1] * (y + 0.5) + m.values[2][2]; \
587 tx = xinc * tx1 + m.values[0][1] * y + m.values[0][2]; \
588 ty = yinc * tx1 + m.values[1][1] * y + m.values[1][2]; \
589 tw = winc * tx1 + m.values[2][1] * y + m.values[2][2]; \
593 out_row += tx1 * components; \
594 for(int x = tx1; x < tx2; x++) \
596 /* Normalize homogeneous coords */ \
616 int row1 = ity - 1; \
618 int row3 = ity + 1; \
619 int row4 = ity + 2; \
620 CLAMP(row1, miny, maxy); \
621 CLAMP(row2, miny, maxy); \
622 CLAMP(row3, miny, maxy); \
623 CLAMP(row4, miny, maxy); \
625 /* Set destination pixels */ \
626 if(!interpolate && x >= server->x && x < server->x + server->w) \
628 if(itx >= server->x && itx < server->x + server->w && \
629 ity >= server->y && ity < server->y + server->h) \
631 type *src = in_rows[ity] + itx * components; \
632 *out_row++ = *src++; \
633 *out_row++ = *src++; \
634 *out_row++ = *src++; \
635 if(components == 4) *out_row++ = *src; \
638 /* Fill with chroma */ \
641 *out_row++ = chroma_offset; \
642 *out_row++ = chroma_offset; \
643 if(components == 4) *out_row++ = 0; \
647 /* Bicubic algorithm */ \
648 if(interpolate && x >= server->x && x < server->x + server->w) \
650 if ((itx + 2) >= server->x && (itx - 1) < server->x + server->w && \
651 (ity + 2) >= server->y && (ity - 1) < server->y + server->h) \
655 /* the fractional error */ \
659 /* Row and column offsets in cubic block */ \
660 int col1 = itx - 1; \
662 int col3 = itx + 1; \
663 int col4 = itx + 2; \
664 CLAMP(col1, minx, maxx); \
665 CLAMP(col2, minx, maxx); \
666 CLAMP(col3, minx, maxx); \
667 CLAMP(col4, minx, maxx); \
668 int col1_offset = col1 * components; \
669 int col2_offset = col2 * components; \
670 int col3_offset = col3 * components; \
671 int col4_offset = col4 * components; \
672 type *row1_ptr = in_rows[row1]; \
673 type *row2_ptr = in_rows[row2]; \
674 type *row3_ptr = in_rows[row3]; \
675 type *row4_ptr = in_rows[row4]; \
676 temp_type r, g, b, a; \
678 r = (temp_type)(transform_cubic(dy, \
679 CUBIC_ROW(row1_ptr, 0x0), \
680 CUBIC_ROW(row2_ptr, 0x0), \
681 CUBIC_ROW(row3_ptr, 0x0), \
682 CUBIC_ROW(row4_ptr, 0x0)) + \
689 g = (temp_type)(transform_cubic(dy, \
690 CUBIC_ROW(row1_ptr, chroma_offset), \
691 CUBIC_ROW(row2_ptr, chroma_offset), \
692 CUBIC_ROW(row3_ptr, chroma_offset), \
693 CUBIC_ROW(row4_ptr, chroma_offset)) + \
695 g += chroma_offset; \
701 b = (temp_type)(transform_cubic(dy, \
702 CUBIC_ROW(row1_ptr, chroma_offset), \
703 CUBIC_ROW(row2_ptr, chroma_offset), \
704 CUBIC_ROW(row3_ptr, chroma_offset), \
705 CUBIC_ROW(row4_ptr, chroma_offset)) + \
707 b += chroma_offset; \
709 if(components == 4) \
715 a = (temp_type)(transform_cubic(dy, \
716 CUBIC_ROW(row1_ptr, 0x0), \
717 CUBIC_ROW(row2_ptr, 0x0), \
718 CUBIC_ROW(row3_ptr, 0x0), \
719 CUBIC_ROW(row4_ptr, 0x0)) + \
723 if(sizeof(type) < 4) \
725 *out_row++ = CLIP(r, 0, max); \
726 *out_row++ = CLIP(g, 0, max); \
727 *out_row++ = CLIP(b, 0, max); \
728 if(components == 4) *out_row++ = CLIP(a, 0, max); \
735 if(components == 4) *out_row++ = a; \
739 /* Fill with chroma */ \
742 *out_row++ = chroma_offset; \
743 *out_row++ = chroma_offset; \
744 if(components == 4) *out_row++ = 0; \
749 out_row += components; \
752 /* increment the transformed coordinates */ \
763 switch(server->input->get_color_model())
766 TRANSFORM(3, float, float, 0x0, 1.0)
769 TRANSFORM(3, unsigned char, int, 0x0, 0xff)
772 TRANSFORM(4, float, float, 0x0, 1.0)
775 TRANSFORM(4, unsigned char, int, 0x0, 0xff)
778 TRANSFORM(3, unsigned char, int, 0x80, 0xff)
781 TRANSFORM(4, unsigned char, int, 0x80, 0xff)
784 TRANSFORM(3, uint16_t, int, 0x0, 0xffff)
786 case BC_RGBA16161616:
787 TRANSFORM(4, uint16_t, int, 0x0, 0xffff)
790 TRANSFORM(3, uint16_t, int, 0x8000, 0xffff)
792 case BC_YUVA16161616:
793 TRANSFORM(4, uint16_t, int, 0x8000, 0xffff)
800 int min_x = server->x * AFFINE_OVERSAMPLE;
801 int min_y = server->y * AFFINE_OVERSAMPLE;
802 int max_x = server->x * AFFINE_OVERSAMPLE + server->w * AFFINE_OVERSAMPLE - 1;
803 int max_y = server->y * AFFINE_OVERSAMPLE + server->h * AFFINE_OVERSAMPLE - 1;
804 float top_w = out_x2 - out_x1;
805 float bottom_w = out_x3 - out_x4;
806 float left_h = out_y4 - out_y1;
807 float right_h = out_y3 - out_y2;
808 float out_w_diff = bottom_w - top_w;
809 float out_left_diff = out_x4 - out_x1;
810 float out_h_diff = right_h - left_h;
811 float out_top_diff = out_y2 - out_y1;
812 float distance1 = DISTANCE(out_x1, out_y1, out_x2, out_y2);
813 float distance2 = DISTANCE(out_x2, out_y2, out_x3, out_y3);
814 float distance3 = DISTANCE(out_x3, out_y3, out_x4, out_y4);
815 float distance4 = DISTANCE(out_x4, out_y4, out_x1, out_y1);
816 float max_v = MAX(distance1, distance3);
817 float max_h = MAX(distance2, distance4);
818 float max_dimension = MAX(max_v, max_h);
819 float min_dimension = MIN(server->h, server->w);
820 float step = min_dimension / max_dimension / AFFINE_OVERSAMPLE;
821 float x_f = server->x;
822 float y_f = server->y;
823 float h_f = server->h;
824 float w_f = server->w;
828 if(server->use_opengl)
836 #define DO_STRETCH(type, components) \
838 type **in_rows = (type**)server->input->get_rows(); \
839 type **out_rows = (type**)server->temp->get_rows(); \
841 for(float in_y = pkg->y1; in_y < pkg->y2; in_y += step) \
844 type *in_row = in_rows[i]; \
845 for(float in_x = x_f; in_x < w_f; in_x += step) \
848 float in_x_fraction = (in_x - x_f) / w_f; \
849 float in_y_fraction = (in_y - y_f) / h_f; \
850 int out_x = (int)((out_x1 + \
851 out_left_diff * in_y_fraction + \
852 (top_w + out_w_diff * in_y_fraction) * in_x_fraction) * \
853 AFFINE_OVERSAMPLE); \
854 int out_y = (int)((out_y1 + \
855 out_top_diff * in_x_fraction + \
856 (left_h + out_h_diff * in_x_fraction) * in_y_fraction) * \
857 AFFINE_OVERSAMPLE); \
858 CLAMP(out_x, min_x, max_x); \
859 CLAMP(out_y, min_y, max_y); \
860 type *dst = out_rows[out_y] + out_x * components; \
861 type *src = in_row + j * components; \
865 if(components == 4) dst[3] = src[3]; \
870 switch(server->input->get_color_model())
876 DO_STRETCH(unsigned char, 3)
882 DO_STRETCH(unsigned char, 4)
885 DO_STRETCH(unsigned char, 3)
888 DO_STRETCH(unsigned char, 4)
891 DO_STRETCH(uint16_t, 3)
893 case BC_RGBA16161616:
894 DO_STRETCH(uint16_t, 4)
897 DO_STRETCH(uint16_t, 3)
899 case BC_YUVA16161616:
900 DO_STRETCH(uint16_t, 4)
915 AffineEngine::AffineEngine(int total_clients,
919 total_clients, total_packages
927 void AffineEngine::init_packages()
929 for(int i = 0; i < get_total_packages(); i++)
931 AffinePackage *package = (AffinePackage*)get_package(i);
932 package->y1 = y + (h * i / get_total_packages());
933 package->y2 = y + (h * (i + 1) / get_total_packages());
937 LoadClient* AffineEngine::new_client()
939 return new AffineUnit(this);
942 LoadPackage* AffineEngine::new_package()
944 return new AffinePackage;
947 void AffineEngine::process(VFrame *output,
961 this->output = output;
973 this->forward = forward;
993 void AffineEngine::rotate(VFrame *output,
997 this->output = output;
1000 this->mode = ROTATE;
1013 pivot_x = x + w / 2;
1014 pivot_y = y + h / 2;
1017 // All subscripts are clockwise around the quadrangle
1018 angle = angle * 2 * M_PI / 360;
1019 double angle1 = atan((double)(pivot_y - y) / (double)(pivot_x - x)) + angle;
1020 double angle2 = atan((double)(x + w - pivot_x) / (double)(pivot_y - y)) + angle;
1021 double angle3 = atan((double)(y + h - pivot_y) / (double)(x + w - pivot_x)) + angle;
1022 double angle4 = atan((double)(pivot_x - x) / (double)(y + h - pivot_y)) + angle;
1023 double radius1 = DISTANCE(x, y, pivot_x, pivot_y);
1024 double radius2 = DISTANCE(x + w, y, pivot_x, pivot_y);
1025 double radius3 = DISTANCE(x + w, y + h, pivot_x, pivot_y);
1026 double radius4 = DISTANCE(x, y + h, pivot_x, pivot_y);
1028 x1 = ((pivot_x - x) - cos(angle1) * radius1) * 100 / w;
1029 y1 = ((pivot_y - y) - sin(angle1) * radius1) * 100 / h;
1030 x2 = ((pivot_x - x) + sin(angle2) * radius2) * 100 / w;
1031 y2 = ((pivot_y - y) - cos(angle2) * radius2) * 100 / h;
1032 x3 = ((pivot_x - x) + cos(angle3) * radius3) * 100 / w;
1033 y3 = ((pivot_y - y) + sin(angle3) * radius3) * 100 / h;
1034 x4 = ((pivot_x - x) - sin(angle4) * radius4) * 100 / w;
1035 y4 = ((pivot_y - y) + cos(angle4) * radius4) * 100 / h;
1037 // printf("AffineEngine::rotate x=%d y=%d w=%d h=%d pivot_x=%d pivot_y=%d angle=%f\n",
1041 // angle * 360 / 2 / M_PI);
1043 // printf(" angle1=%f angle2=%f angle3=%f angle4=%f\n",
1044 // angle1 * 360 / 2 / M_PI,
1045 // angle2 * 360 / 2 / M_PI,
1046 // angle3 * 360 / 2 / M_PI,
1047 // angle4 * 360 / 2 / M_PI);
1049 // printf(" radius1=%f radius2=%f radius3=%f radius4=%f\n",
1055 // printf(" x1=%f y1=%f x2=%f y2=%f x3=%f y3=%f x4=%f y4=%f\n",
1069 // process_packages();
1072 void AffineEngine::set_viewport(int x, int y, int w, int h)
1081 void AffineEngine::set_opengl(int value)
1083 this->use_opengl = value;
1086 void AffineEngine::set_pivot(int x, int y)
1090 this->user_pivot = 1;
1093 void AffineEngine::unset_pivot()
1098 void AffineEngine::unset_viewport()