Home | History | Annotate | Download | only in vega
      1 /**************************************************************************
      2  *
      3  * Copyright 2009 VMware, Inc.  All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     20  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  **************************************************************************/
     26 
     27 #include "VG/openvg.h"
     28 #include "VG/vgu.h"
     29 
     30 #include "matrix.h"
     31 #include "path.h"
     32 #include "handle.h"
     33 
     34 #include "util/u_debug.h"
     35 #include "util/u_pointer.h"
     36 
     37 #include <math.h>
     38 #include <assert.h>
     39 
     40 
     41 static void vgu_append_float_coords(VGPath path,
     42                                     const VGubyte *cmds,
     43                                     VGint num_cmds,
     44                                     const VGfloat *coords,
     45                                     VGint num_coords)
     46 {
     47    VGubyte common_data[40 * sizeof(VGfloat)];
     48    struct path *p = handle_to_path(path);
     49 
     50    vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
     51    vgAppendPathData(path, num_cmds, cmds, common_data);
     52 }
     53 
     54 VGUErrorCode vguLine(VGPath path,
     55                      VGfloat x0, VGfloat y0,
     56                      VGfloat x1, VGfloat y1)
     57 {
     58    static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
     59    VGfloat coords[4];
     60    VGbitfield caps;
     61 
     62    if (path == VG_INVALID_HANDLE) {
     63       return VGU_BAD_HANDLE_ERROR;
     64    }
     65    caps = vgGetPathCapabilities(path);
     66    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
     67       return VGU_PATH_CAPABILITY_ERROR;
     68    }
     69 
     70    coords[0] = x0;
     71    coords[1] = y0;
     72    coords[2] = x1;
     73    coords[3] = y1;
     74 
     75    vgu_append_float_coords(path, cmds, 2, coords, 4);
     76 
     77    return VGU_NO_ERROR;
     78 }
     79 
     80 VGUErrorCode vguPolygon(VGPath path,
     81                         const VGfloat * points,
     82                         VGint count,
     83                         VGboolean closed)
     84 {
     85    VGubyte *cmds;
     86    VGfloat *coords;
     87    VGbitfield caps;
     88    VGint i;
     89 
     90    if (path == VG_INVALID_HANDLE) {
     91       return VGU_BAD_HANDLE_ERROR;
     92    }
     93 
     94    if (!points || count <= 0 || !is_aligned(points)) {
     95       return VGU_ILLEGAL_ARGUMENT_ERROR;
     96    }
     97 
     98    caps = vgGetPathCapabilities(path);
     99    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
    100       return VGU_PATH_CAPABILITY_ERROR;
    101    }
    102 
    103    cmds   = malloc(sizeof(VGubyte) * count + 1);
    104    coords = malloc(sizeof(VGfloat) * count * 2);
    105 
    106    cmds[0] = VG_MOVE_TO_ABS;
    107    coords[0] = points[0];
    108    coords[1] = points[1];
    109    for (i = 1; i < count; ++i) {
    110       cmds[i] = VG_LINE_TO_ABS;
    111       coords[2*i + 0] = points[2*i + 0];
    112       coords[2*i + 1] = points[2*i + 1];
    113    }
    114 
    115    if (closed) {
    116       cmds[i] = VG_CLOSE_PATH;
    117       ++i;
    118    }
    119 
    120    vgu_append_float_coords(path, cmds, i, coords, 2*i);
    121 
    122    free(cmds);
    123    free(coords);
    124 
    125    return VGU_NO_ERROR;
    126 }
    127 
    128 VGUErrorCode  vguRect(VGPath path,
    129                       VGfloat x, VGfloat y,
    130                       VGfloat width, VGfloat height)
    131 {
    132    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
    133                                   VG_HLINE_TO_REL,
    134                                   VG_VLINE_TO_REL,
    135                                   VG_HLINE_TO_REL,
    136                                   VG_CLOSE_PATH
    137    };
    138    VGfloat coords[5];
    139    VGbitfield caps;
    140 
    141    if (path == VG_INVALID_HANDLE) {
    142       return VGU_BAD_HANDLE_ERROR;
    143    }
    144    caps = vgGetPathCapabilities(path);
    145    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
    146       return VGU_PATH_CAPABILITY_ERROR;
    147    }
    148    if (width <= 0 || height <= 0) {
    149       return VGU_ILLEGAL_ARGUMENT_ERROR;
    150    }
    151 
    152    coords[0] =  x;
    153    coords[1] =  y;
    154    coords[2] =  width;
    155    coords[3] =  height;
    156    coords[4] = -width;
    157 
    158    vgu_append_float_coords(path, cmds, 5, coords, 5);
    159 
    160    return VGU_NO_ERROR;
    161 }
    162 
    163 VGUErrorCode vguRoundRect(VGPath path,
    164                           VGfloat x, VGfloat y,
    165                           VGfloat width,
    166                           VGfloat height,
    167                           VGfloat arcWidth,
    168                           VGfloat arcHeight)
    169 {
    170    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
    171                                   VG_HLINE_TO_REL,
    172                                   VG_SCCWARC_TO_REL,
    173                                   VG_VLINE_TO_REL,
    174                                   VG_SCCWARC_TO_REL,
    175                                   VG_HLINE_TO_REL,
    176                                   VG_SCCWARC_TO_REL,
    177                                   VG_VLINE_TO_REL,
    178                                   VG_SCCWARC_TO_REL,
    179                                   VG_CLOSE_PATH
    180    };
    181    VGfloat c[26];
    182    VGbitfield caps;
    183 
    184    if (path == VG_INVALID_HANDLE) {
    185       return VGU_BAD_HANDLE_ERROR;
    186    }
    187    caps = vgGetPathCapabilities(path);
    188    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
    189       return VGU_PATH_CAPABILITY_ERROR;
    190    }
    191    if (width <= 0 || height <= 0) {
    192       return VGU_ILLEGAL_ARGUMENT_ERROR;
    193    }
    194 
    195    c[0] =  x + arcWidth/2; c[1] =  y;
    196 
    197    c[2] = width - arcWidth;
    198 
    199    c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0;
    200    c[6] = arcWidth/2; c[7] = arcHeight/2;
    201 
    202    c[8] = height - arcHeight;
    203 
    204    c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0;
    205    c[12] = -arcWidth/2; c[13] = arcHeight/2;
    206 
    207    c[14] = -(width - arcWidth);
    208 
    209    c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0;
    210    c[18] = -arcWidth/2; c[19] = -arcHeight/2;
    211 
    212    c[20] = -(height - arcHeight);
    213 
    214    c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0;
    215    c[24] = arcWidth/2; c[25] = -arcHeight/2;
    216 
    217    vgu_append_float_coords(path, cmds, 10, c, 26);
    218 
    219    return VGU_NO_ERROR;
    220 }
    221 
    222 VGUErrorCode vguEllipse(VGPath path,
    223                         VGfloat cx, VGfloat cy,
    224                         VGfloat width,
    225                         VGfloat height)
    226 {
    227    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
    228                                   VG_SCCWARC_TO_REL,
    229                                   VG_SCCWARC_TO_REL,
    230                                   VG_CLOSE_PATH
    231    };
    232    VGfloat coords[12];
    233    VGbitfield caps;
    234 
    235    if (path == VG_INVALID_HANDLE) {
    236       return VGU_BAD_HANDLE_ERROR;
    237    }
    238    caps = vgGetPathCapabilities(path);
    239    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
    240       return VGU_PATH_CAPABILITY_ERROR;
    241    }
    242    if (width <= 0 || height <= 0) {
    243       return VGU_ILLEGAL_ARGUMENT_ERROR;
    244    }
    245 
    246    coords[0] = cx + width/2; coords[1] = cy;
    247 
    248    coords[2] = width/2; coords[3] = height/2; coords[4] = 0;
    249    coords[5] = -width; coords[6] = 0;
    250 
    251    coords[7] = width/2; coords[8] = height/2; coords[9] = 0;
    252    coords[10] = width; coords[11] = 0;
    253 
    254    vgu_append_float_coords(path, cmds, 4, coords, 11);
    255 
    256    return VGU_NO_ERROR;
    257 }
    258 
    259 VGUErrorCode vguArc(VGPath path,
    260                     VGfloat x, VGfloat y,
    261                     VGfloat width, VGfloat height,
    262                     VGfloat startAngle,
    263                     VGfloat angleExtent,
    264                     VGUArcType arcType)
    265 {
    266    VGubyte cmds[11];
    267    VGfloat coords[40];
    268    VGbitfield caps;
    269    VGfloat last = startAngle + angleExtent;
    270    VGint i, c = 0;
    271 
    272    if (path == VG_INVALID_HANDLE) {
    273       return VGU_BAD_HANDLE_ERROR;
    274    }
    275    caps = vgGetPathCapabilities(path);
    276    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
    277       return VGU_PATH_CAPABILITY_ERROR;
    278    }
    279    if (width <= 0 || height <= 0) {
    280       return VGU_ILLEGAL_ARGUMENT_ERROR;
    281    }
    282    if (arcType != VGU_ARC_OPEN &&
    283        arcType != VGU_ARC_CHORD &&
    284        arcType != VGU_ARC_PIE) {
    285       return VGU_ILLEGAL_ARGUMENT_ERROR;
    286    }
    287 
    288    cmds[c] = VG_MOVE_TO_ABS; ++c;
    289    coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2;
    290    coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2;
    291 #ifdef DEBUG_VGUARC
    292    debug_printf("start [%f, %f]\n", coords[0], coords[1]);
    293 #endif
    294    i = 2;
    295    if (angleExtent > 0) {
    296       VGfloat angle = startAngle + 180;
    297       while (angle < last) {
    298          cmds[c] = VG_SCCWARC_TO_ABS; ++c;
    299          coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
    300          coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2;
    301          coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2;
    302 #ifdef DEBUG_VGUARC
    303          debug_printf("1 [%f, %f]\n", coords[i+3],
    304                       coords[i+4]);
    305 #endif
    306          i += 5;
    307          angle += 180;
    308       }
    309       cmds[c] = VG_SCCWARC_TO_ABS; ++c;
    310       coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
    311       coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2;
    312       coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2;
    313 #ifdef DEBUG_VGUARC
    314       debug_printf("2 [%f, %f]\n", coords[i+3],
    315                    coords[i+4]);
    316 #endif
    317       i += 5;
    318    } else {
    319       VGfloat angle = startAngle - 180;
    320       while (angle > last) {
    321          cmds[c] = VG_SCWARC_TO_ABS; ++c;
    322          coords[i] =  width/2; coords[i+1] = height/2; coords[i+2] = 0;
    323          coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2;
    324          coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2;
    325 #ifdef DEBUG_VGUARC
    326          debug_printf("3 [%f, %f]\n", coords[i+3],
    327                       coords[i+4]);
    328 #endif
    329          angle -= 180;
    330          i += 5;
    331       }
    332       cmds[c] = VG_SCWARC_TO_ABS; ++c;
    333       coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
    334       coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2;
    335       coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2;
    336 #ifdef DEBUG_VGUARC
    337       debug_printf("4 [%f, %f]\n", coords[i+3],
    338                    coords[i+4]);
    339 #endif
    340       i += 5;
    341    }
    342 
    343    if (arcType == VGU_ARC_PIE) {
    344       cmds[c] = VG_LINE_TO_ABS; ++c;
    345       coords[i] = x; coords[i + 1] = y;
    346       i += 2;
    347    }
    348    if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) {
    349       cmds[c] = VG_CLOSE_PATH;
    350       ++c;
    351    }
    352 
    353    assert(c < 11);
    354 
    355    vgu_append_float_coords(path, cmds, c, coords, i);
    356 
    357    return VGU_NO_ERROR;
    358 }
    359 
    360 VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
    361                                         VGfloat sx1, VGfloat sy1,
    362                                         VGfloat sx2, VGfloat sy2,
    363                                         VGfloat sx3, VGfloat sy3,
    364                                         VGfloat * matrix)
    365 {
    366    struct matrix mat;
    367 
    368    if (!matrix || !is_aligned(matrix))
    369       return VGU_ILLEGAL_ARGUMENT_ERROR;
    370 
    371    if (!matrix_quad_to_square(sx0, sy0,
    372                               sx1, sy1,
    373                               sx2, sy2,
    374                               sx3, sy3,
    375                               &mat))
    376       return VGU_BAD_WARP_ERROR;
    377 
    378    if (!matrix_is_invertible(&mat))
    379       return VGU_BAD_WARP_ERROR;
    380 
    381    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
    382 
    383    return VGU_NO_ERROR;
    384 }
    385 
    386 VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
    387                                         VGfloat dx1, VGfloat dy1,
    388                                         VGfloat dx2, VGfloat dy2,
    389                                         VGfloat dx3, VGfloat dy3,
    390                                         VGfloat * matrix)
    391 {
    392    struct matrix mat;
    393 
    394    if (!matrix || !is_aligned(matrix))
    395       return VGU_ILLEGAL_ARGUMENT_ERROR;
    396 
    397    if (!matrix_square_to_quad(dx0, dy0,
    398                               dx1, dy1,
    399                               dx2, dy2,
    400                               dx3, dy3,
    401                               &mat))
    402       return VGU_BAD_WARP_ERROR;
    403 
    404    if (!matrix_is_invertible(&mat))
    405       return VGU_BAD_WARP_ERROR;
    406 
    407    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
    408 
    409    return VGU_NO_ERROR;
    410 }
    411 
    412 VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
    413                                       VGfloat dx1, VGfloat dy1,
    414                                       VGfloat dx2, VGfloat dy2,
    415                                       VGfloat dx3, VGfloat dy3,
    416                                       VGfloat sx0, VGfloat sy0,
    417                                       VGfloat sx1, VGfloat sy1,
    418                                       VGfloat sx2, VGfloat sy2,
    419                                       VGfloat sx3, VGfloat sy3,
    420                                       VGfloat * matrix)
    421 {
    422    struct matrix mat;
    423 
    424    if (!matrix || !is_aligned(matrix))
    425       return VGU_ILLEGAL_ARGUMENT_ERROR;
    426 
    427    if (!matrix_quad_to_quad(dx0, dy0,
    428                             dx1, dy1,
    429                             dx2, dy2,
    430                             dx3, dy3,
    431                             sx0, sy0,
    432                             sx1, sy1,
    433                             sx2, sy2,
    434                             sx3, sy3,
    435                             &mat))
    436       return VGU_BAD_WARP_ERROR;
    437 
    438    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
    439 
    440    return VGU_NO_ERROR;
    441 }
    442