Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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.  
  29. #include "vg_context.h"
  30. #include "handle.h"
  31. #include "path.h"
  32. #include "api.h"
  33.  
  34. #include "pipe/p_context.h"
  35.  
  36. VGPath vegaCreatePath(VGint pathFormat,
  37.                       VGPathDatatype datatype,
  38.                       VGfloat scale, VGfloat bias,
  39.                       VGint segmentCapacityHint,
  40.                       VGint coordCapacityHint,
  41.                       VGbitfield capabilities)
  42. {
  43.    struct vg_context *ctx = vg_current_context();
  44.  
  45.    if (pathFormat != VG_PATH_FORMAT_STANDARD) {
  46.       vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR);
  47.       return VG_INVALID_HANDLE;
  48.    }
  49.    if (datatype < VG_PATH_DATATYPE_S_8 ||
  50.        datatype > VG_PATH_DATATYPE_F) {
  51.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  52.       return VG_INVALID_HANDLE;
  53.    }
  54.    if (!scale) {
  55.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  56.       return VG_INVALID_HANDLE;
  57.    }
  58.  
  59.    return path_to_handle(path_create(datatype, scale, bias,
  60.                                      segmentCapacityHint, coordCapacityHint,
  61.                                      capabilities));
  62. }
  63.  
  64. void vegaClearPath(VGPath path, VGbitfield capabilities)
  65. {
  66.    struct vg_context *ctx = vg_current_context();
  67.    struct path *p = 0;
  68.  
  69.    if (path == VG_INVALID_HANDLE) {
  70.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  71.       return;
  72.    }
  73.  
  74.    p = handle_to_path(path);
  75.    path_clear(p, capabilities);
  76. }
  77.  
  78. void vegaDestroyPath(VGPath p)
  79. {
  80.    struct path *path = 0;
  81.    struct vg_context *ctx = vg_current_context();
  82.  
  83.    if (p == VG_INVALID_HANDLE) {
  84.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  85.       return;
  86.    }
  87.  
  88.    path = handle_to_path(p);
  89.    path_destroy(path);
  90. }
  91.  
  92. void vegaRemovePathCapabilities(VGPath path,
  93.                                 VGbitfield capabilities)
  94. {
  95.    struct vg_context *ctx = vg_current_context();
  96.    VGbitfield current;
  97.    struct path *p;
  98.  
  99.    if (path == VG_INVALID_HANDLE) {
  100.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  101.       return;
  102.    }
  103.  
  104.    p = handle_to_path(path);
  105.    current = path_capabilities(p);
  106.    path_set_capabilities(p, (current &
  107.                              (~(capabilities & VG_PATH_CAPABILITY_ALL))));
  108. }
  109.  
  110. VGbitfield vegaGetPathCapabilities(VGPath path)
  111. {
  112.    struct vg_context *ctx = vg_current_context();
  113.    struct path *p = 0;
  114.  
  115.    if (path == VG_INVALID_HANDLE) {
  116.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  117.       return 0;
  118.    }
  119.    p = handle_to_path(path);
  120.    return path_capabilities(p);
  121. }
  122.  
  123. void vegaAppendPath(VGPath dstPath, VGPath srcPath)
  124. {
  125.    struct vg_context *ctx = vg_current_context();
  126.    struct path *src, *dst;
  127.  
  128.    if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
  129.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  130.       return;
  131.    }
  132.    src = handle_to_path(srcPath);
  133.    dst = handle_to_path(dstPath);
  134.  
  135.    if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) ||
  136.        !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) {
  137.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  138.       return;
  139.    }
  140.    path_append_path(dst, src);
  141. }
  142.  
  143. void vegaAppendPathData(VGPath dstPath,
  144.                         VGint numSegments,
  145.                         const VGubyte * pathSegments,
  146.                         const void * pathData)
  147. {
  148.    struct vg_context *ctx = vg_current_context();
  149.    struct path *p = 0;
  150.    VGint i;
  151.  
  152.    if (dstPath == VG_INVALID_HANDLE) {
  153.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  154.       return;
  155.    }
  156.    if (!pathSegments) {
  157.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  158.       return;
  159.    }
  160.    if (numSegments <= 0) {
  161.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  162.       return;
  163.    }
  164.    for (i = 0; i < numSegments; ++i) {
  165.       if (pathSegments[i] > VG_LCWARC_TO_REL) {
  166.          vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  167.          return;
  168.       }
  169.    }
  170.  
  171.    p = handle_to_path(dstPath);
  172.  
  173.    if (!p || !is_aligned_to(p, path_datatype_size(p))) {
  174.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  175.       return;
  176.    }
  177.  
  178.    if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) {
  179.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  180.       return;
  181.    }
  182.  
  183.    path_append_data(p, numSegments, pathSegments, pathData);
  184. }
  185.  
  186. void vegaModifyPathCoords(VGPath dstPath,
  187.                           VGint startIndex,
  188.                           VGint numSegments,
  189.                           const void * pathData)
  190. {
  191.    struct vg_context *ctx = vg_current_context();
  192.    struct path *p = 0;
  193.  
  194.    if (dstPath == VG_INVALID_HANDLE) {
  195.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  196.       return;
  197.    }
  198.    if (startIndex < 0 || numSegments <= 0) {
  199.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  200.       return;
  201.    }
  202.  
  203.    p = handle_to_path(dstPath);
  204.  
  205.    if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
  206.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  207.       return;
  208.    }
  209.  
  210.    if (startIndex + numSegments > path_num_segments(p)) {
  211.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  212.       return;
  213.    }
  214.    if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) {
  215.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  216.       return;
  217.    }
  218.    path_modify_coords(p, startIndex, numSegments, pathData);
  219. }
  220.  
  221. void vegaTransformPath(VGPath dstPath, VGPath srcPath)
  222. {
  223.    struct vg_context *ctx = vg_current_context();
  224.    struct path *src = 0, *dst = 0;
  225.  
  226.    if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
  227.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  228.       return;
  229.    }
  230.    src = handle_to_path(srcPath);
  231.    dst = handle_to_path(dstPath);
  232.  
  233.    if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) ||
  234.        !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) {
  235.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  236.       return;
  237.    }
  238.    path_transform(dst, src);
  239. }
  240.  
  241. VGboolean vegaInterpolatePath(VGPath dstPath,
  242.                               VGPath startPath,
  243.                               VGPath endPath,
  244.                               VGfloat amount)
  245. {
  246.    struct vg_context *ctx = vg_current_context();
  247.    struct path *start = 0, *dst = 0, *end = 0;
  248.  
  249.    if (dstPath == VG_INVALID_HANDLE ||
  250.        startPath == VG_INVALID_HANDLE ||
  251.        endPath == VG_INVALID_HANDLE) {
  252.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  253.       return VG_FALSE;
  254.    }
  255.    dst = handle_to_path(dstPath);
  256.    start = handle_to_path(startPath);
  257.    end = handle_to_path(endPath);
  258.  
  259.    if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
  260.        !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
  261.        !(path_capabilities(end) & VG_PATH_CAPABILITY_INTERPOLATE_FROM)) {
  262.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  263.       return VG_FALSE;
  264.    }
  265.  
  266.    return path_interpolate(dst,
  267.                            start, end, amount);
  268. }
  269.  
  270. VGfloat vegaPathLength(VGPath path,
  271.                        VGint startSegment,
  272.                        VGint numSegments)
  273. {
  274.    struct vg_context *ctx = vg_current_context();
  275.    struct path *p = 0;
  276.  
  277.    if (path == VG_INVALID_HANDLE) {
  278.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  279.       return -1;
  280.    }
  281.    if (startSegment < 0) {
  282.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  283.       return -1;
  284.    }
  285.    if (numSegments <= 0) {
  286.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  287.       return -1;
  288.    }
  289.    p = handle_to_path(path);
  290.  
  291.    if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) {
  292.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  293.       return -1;
  294.    }
  295.    if (startSegment + numSegments > path_num_segments(p)) {
  296.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  297.       return -1;
  298.    }
  299.  
  300.    return path_length(p, startSegment, numSegments);
  301. }
  302.  
  303. void vegaPointAlongPath(VGPath path,
  304.                         VGint startSegment,
  305.                         VGint numSegments,
  306.                         VGfloat distance,
  307.                         VGfloat * x, VGfloat * y,
  308.                         VGfloat * tangentX,
  309.                         VGfloat * tangentY)
  310. {
  311.    struct vg_context *ctx = vg_current_context();
  312.    struct path *p = 0;
  313.    VGbitfield caps;
  314.  
  315.    if (path == VG_INVALID_HANDLE) {
  316.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  317.       return;
  318.    }
  319.    if (startSegment < 0) {
  320.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  321.       return;
  322.    }
  323.    if (numSegments <= 0) {
  324.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  325.       return;
  326.    }
  327.  
  328.    if (!is_aligned(x) || !is_aligned(y) ||
  329.        !is_aligned(tangentX) || !is_aligned(tangentY)) {
  330.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  331.       return;
  332.    }
  333.  
  334.    p = handle_to_path(path);
  335.  
  336.    caps = path_capabilities(p);
  337.    if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) ||
  338.        !(caps & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)) {
  339.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  340.       return;
  341.    }
  342.  
  343.    if (startSegment + numSegments > path_num_segments(p)) {
  344.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  345.       return;
  346.    }
  347.  
  348.    {
  349.       VGfloat point[2], normal[2];
  350.       path_point(p, startSegment, numSegments, distance,
  351.                  point, normal);
  352.       if (x)
  353.          *x = point[0];
  354.       if (y)
  355.          *y = point[1];
  356.       if (tangentX)
  357.          *tangentX = -normal[1];
  358.       if (tangentY)
  359.          *tangentY = normal[0];
  360.    }
  361. }
  362.  
  363. void vegaPathBounds(VGPath path,
  364.                     VGfloat * minX,
  365.                     VGfloat * minY,
  366.                     VGfloat * width,
  367.                     VGfloat * height)
  368. {
  369.    struct vg_context *ctx = vg_current_context();
  370.    struct path *p = 0;
  371.    VGbitfield caps;
  372.  
  373.    if (path == VG_INVALID_HANDLE) {
  374.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  375.       return;
  376.    }
  377.  
  378.    if (!minX || !minY || !width || !height) {
  379.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  380.       return;
  381.    }
  382.  
  383.    if (!is_aligned(minX) || !is_aligned(minY) ||
  384.        !is_aligned(width) || !is_aligned(height)) {
  385.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  386.       return;
  387.    }
  388.  
  389.    p = handle_to_path(path);
  390.  
  391.    caps = path_capabilities(p);
  392.    if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) {
  393.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  394.       return;
  395.    }
  396.  
  397.    path_bounding_rect(p, minX, minY, width, height);
  398. }
  399.  
  400. void vegaPathTransformedBounds(VGPath path,
  401.                                VGfloat * minX,
  402.                                VGfloat * minY,
  403.                                VGfloat * width,
  404.                                VGfloat * height)
  405. {
  406.    struct vg_context *ctx = vg_current_context();
  407.    struct path *p = 0;
  408.    VGbitfield caps;
  409.  
  410.    if (path == VG_INVALID_HANDLE) {
  411.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  412.       return;
  413.    }
  414.  
  415.    if (!minX || !minY || !width || !height) {
  416.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  417.       return;
  418.    }
  419.  
  420.    if (!is_aligned(minX) || !is_aligned(minY) ||
  421.        !is_aligned(width) || !is_aligned(height)) {
  422.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  423.       return;
  424.    }
  425.  
  426.    p = handle_to_path(path);
  427.  
  428.    caps = path_capabilities(p);
  429.    if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) {
  430.       vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
  431.       return;
  432.    }
  433.  
  434. #if 0
  435.    /* faster, but seems to have precision problems... */
  436.    path_bounding_rect(p, minX, minY, width, height);
  437.    if (*width > 0 && *height > 0) {
  438.       VGfloat pts[] = {*minX,          *minY,
  439.                        *minX + *width, *minY,
  440.                        *minX + *width, *minY + *height,
  441.                        *minX,          *minY + *height};
  442.       struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix;
  443.       VGfloat maxX, maxY;
  444.       matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1);
  445.       matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3);
  446.       matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5);
  447.       matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7);
  448.       *minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6])));
  449.       *minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7])));
  450.       maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6])));
  451.       maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7])));
  452.       *width  = maxX - *minX;
  453.       *height = maxY - *minY;
  454.    }
  455. #else
  456.    {
  457.       struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0,
  458.                                      0, 0, VG_PATH_CAPABILITY_ALL);
  459.       path_transform(dst, p);
  460.       path_bounding_rect(dst, minX, minY, width, height);
  461.       path_destroy(dst);
  462.    }
  463. #endif
  464. }
  465.  
  466.  
  467. void vegaDrawPath(VGPath path, VGbitfield paintModes)
  468. {
  469.    struct vg_context *ctx = vg_current_context();
  470.    struct path *p = handle_to_path(path);
  471.  
  472.    if (path == VG_INVALID_HANDLE) {
  473.       vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
  474.       return;
  475.    }
  476.  
  477.    if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) {
  478.       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
  479.       return;
  480.    }
  481.  
  482.    if (path_is_empty(p))
  483.       return;
  484.    path_render(p, paintModes,
  485.          &ctx->state.vg.path_user_to_surface_matrix);
  486. }
  487.  
  488.