os/graphics/graphicscomposition/openwfcompositionengine/composition/src/wfcelement.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* Copyright (c) 2009-2010 The Khronos Group Inc.
     2  * Portions copyright (c) 2009-2010  Nokia Corporation and/or its subsidiary(-ies)
     3  *
     4  * Permission is hereby granted, free of charge, to any person obtaining a
     5  * copy of this software and/or associated documentation files (the
     6  * "Materials"), to deal in the Materials without restriction, including
     7  * without limitation the rights to use, copy, modify, merge, publish,
     8  * distribute, sublicense, and/or sell copies of the Materials, and to
     9  * permit persons to whom the Materials are furnished to do so, subject to
    10  * the following conditions:
    11  *
    12  * The above copyright notice and this permission notice shall be included
    13  * in all copies or substantial portions of the Materials.
    14  *
    15  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    21  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    22  */
    23 /*! \ingroup wfc
    24  *  \file wfcelement.c
    25  *
    26  *  \brief SI Element handling
    27  */
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <math.h>
    31 #include <string.h>
    32 
    33 #include <WF/wfc.h>
    34 
    35 #include "wfcelement.h"
    36 #include "wfccontext.h"
    37 #include "wfcdevice.h"
    38 #include "wfcstructs.h"
    39 #include "wfcimageprovider.h"
    40 #include "owfnativestream.h"
    41 #include "owfattributes.h"
    42 #include "owfmemory.h"
    43 #include "owfobject.h"
    44 
    45 #include "owfdebug.h"
    46 
    47 #ifdef __cplusplus
    48 extern "C" {
    49 #endif
    50 
    51 #define FIRST_ELEMENT_HANDLE    3000
    52 
    53 #define FAIL_IF(c,e)        if (c) { return e; }
    54 
    55 
    56 static const WFCbitfield    validTransparencyModes[] = {
    57                                 WFC_TRANSPARENCY_NONE,
    58                                 WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA,
    59                                 WFC_TRANSPARENCY_SOURCE,
    60                                 WFC_TRANSPARENCY_MASK,
    61                                 WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
    62                                     WFC_TRANSPARENCY_SOURCE,
    63                                 WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA |
    64                                     WFC_TRANSPARENCY_MASK
    65                             };
    66 
    67 /*---------------------------------------------------------------------------
    68  *
    69  *----------------------------------------------------------------------------*/
    70 void
    71 WFC_Element_Initialize(WFC_ELEMENT* element)
    72 {
    73     element->dstRect[0]         = 0;
    74     element->dstRect[1]         = 0;
    75     element->dstRect[2]         = 0;
    76     element->dstRect[3]         = 0;
    77     element->srcRect[0]         = 0;
    78     element->srcRect[1]         = 0;
    79     element->srcRect[2]         = 0;
    80     element->srcRect[3]         = 0;
    81 
    82     element->source             = WFC_INVALID_HANDLE;
    83     element->sourceFlip         = WFC_FALSE;
    84     element->sourceRotation     = WFC_ROTATION_0;
    85     element->sourceScaleFilter  = WFC_SCALE_FILTER_NONE;
    86     element->transparencyTypes  = 0;
    87     element->globalAlpha        = OWF_ALPHA_MAX_VALUE;
    88     element->maskHandle         = WFC_INVALID_HANDLE;
    89     element->sourceHandle       = WFC_INVALID_HANDLE;
    90 }
    91 
    92 /*---------------------------------------------------------------------------
    93  *
    94  *----------------------------------------------------------------------------*/
    95 OWF_API_CALL void
    96 WFC_Element_Destroy(WFC_ELEMENT* element)
    97 {
    98     if (element)
    99     {
   100         DPRINT(("WFC_Element_Destroy"));
   101 
   102         DPRINT(("  element = %p (%d)", element, element->handle));
   103 
   104         DESTROY(element->cachedSource);
   105         DESTROY(element->cachedMask);
   106 
   107         DPRINT(("  cachedSource = %p (%d)", element->cachedSource,
   108                                             element->cachedSource ?
   109                                                 element->cachedSource->handle :
   110                                                 0));
   111         DPRINT(("  cachedMask = %p (%d)", element->cachedMask,
   112                                           element->cachedMask ?
   113                                               element->cachedMask->handle :
   114                                               0));
   115 
   116         DESTROY(element->source);
   117         DESTROY(element->mask);
   118 
   119         DPRINT(("  source = %p (%d)", element->source,
   120                                       element->source ?
   121                                           element->source->handle :
   122                                           0));
   123         DPRINT(("  mask = %p (%d)", element->mask,
   124                                     element->mask ?
   125                                         element->mask->handle :
   126                                         0));
   127         DESTROY(element->context);
   128 
   129         OWF_Pool_PutObject(element);
   130     }
   131 }
   132 
   133 /*---------------------------------------------------------------------------
   134  *  Create new element into context
   135  *
   136  *  \param context Context into which to create the element
   137  *
   138  *  \return New element object or NULL
   139  *----------------------------------------------------------------------------*/
   140 OWF_API_CALL WFC_ELEMENT*
   141 WFC_Element_Create(WFC_CONTEXT* context)
   142 {
   143     static WFCint           nextElementHandle = FIRST_ELEMENT_HANDLE;
   144     WFC_ELEMENT*            element;
   145 	
   146 	OWF_ASSERT(context);
   147 
   148     element = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
   149 
   150     if (element)
   151     {
   152         WFC_Element_Initialize(element);
   153 
   154         element->handle = nextElementHandle++;
   155 
   156         ADDREF(element->context, context);
   157         element->device = context->device;
   158     }
   159     return element;
   160 }
   161 
   162 /*---------------------------------------------------------------------------
   163  *
   164  *----------------------------------------------------------------------------*/
   165 OWF_API_CALL WFC_ELEMENT*
   166 WFC_Element_Clone(WFC_ELEMENT* element)
   167 {
   168     WFC_ELEMENT*        clone;
   169     WFC_CONTEXT*        context;
   170 
   171     OWF_ASSERT(element);
   172 
   173     DPRINT(("WFC_Element_Clone: element = %d, context = %d", element->handle,
   174             element->context->handle));
   175 
   176     context = CONTEXT(element->context);
   177     clone = (WFC_ELEMENT*)OWF_Pool_GetObject(context->elementPool);
   178 
   179     if (clone)
   180     {
   181         WFC_Element_Initialize(clone);
   182 
   183         clone->handle           = element->handle;
   184 
   185         clone->sourceFlip       = element->sourceFlip;
   186         clone->sourceRotation   = element->sourceRotation;
   187         clone->sourceScaleFilter= element->sourceScaleFilter;
   188         clone->transparencyTypes= element->transparencyTypes;
   189         clone->globalAlpha      = element->globalAlpha;
   190         clone->maskHandle       = element->maskHandle;
   191         clone->sourceHandle     = element->sourceHandle;
   192 
   193         ADDREF(clone->cachedMask, element->cachedMask);
   194         ADDREF(clone->cachedSource, element->cachedSource);
   195 
   196         ADDREF(clone->mask,     element->mask);
   197         ADDREF(clone->source,   element->source);
   198         clone->device = element->device;
   199 
   200         ADDREF(clone->context,  element->context);
   201 
   202         memcpy(clone->srcRect,  element->srcRect, 4 * sizeof(WFCfloat));
   203         memcpy(clone->dstRect,  element->dstRect, 4 * sizeof(WFCfloat));
   204 
   205     }
   206 
   207     return clone;
   208 }
   209 
   210 /*---------------------------------------------------------------------------
   211  *
   212  *----------------------------------------------------------------------------*/
   213 static WFCboolean WFC_Element_ClampRectangle(const char* rtype,
   214                                              WFCfloat* rect)
   215 {
   216     /*
   217      * int -> float conversion:
   218      * ------------------------
   219      *
   220      * above 2^24 we start to lose precision when performing
   221      * conversions between floats & ints, thus we must clamp
   222      * values above in order to avoid nasty sign-change effects
   223      * and other weird side-effects.
   224      *
   225      */
   226 
   227     const WFCfloat          LIMIT = 1.6777216E7f;
   228     WFCint                  i;
   229     WFCboolean              clamped = WFC_FALSE;
   230 
   231     /* Prevent compiler warning when DPRINT is disabled */
   232     (void) rtype;
   233 
   234     for (i = 0; i < 4; i++)
   235     {
   236         if (fabs(rect[i]) > LIMIT)
   237         {
   238 #ifdef DEBUG
   239             static const char* coord[4] = {"x", "y", "width", "height"};
   240             (void)coord[0];
   241 #endif
   242 
   243             DPRINT(("  Warning: Precision loss in element's %s rectangle's "
   244                     "%s coordinate.",
   245                     rtype, coord[i]));
   246 
   247             rect[i] = rect[i] < 0 ? -LIMIT : LIMIT;
   248 
   249             clamped = WFC_TRUE;
   250         }
   251     }
   252     return clamped;
   253 }
   254 /*===========================================================================
   255  *
   256  * Attribute set-time checking functions. These are used for checking
   257  * the attributes before saving them into elements. Attributes are validated
   258  * for 2nd time during commit, where e.g. destination rectangle size vs.
   259  * mask size dependency is checked.
   260  *
   261  *============================================================================*/
   262 
   263 /*---------------------------------------------------------------------------
   264  *
   265  *----------------------------------------------------------------------------*/
   266 static WFCErrorCode
   267 WFC_Element_ValidateSourceRectangle(WFC_ELEMENT* element,
   268                                     WFCfloat* rect)
   269 {
   270     WFCErrorCode            result = WFC_ERROR_NONE;
   271     
   272 #ifndef DEBUG
   273     (void) element;
   274 #endif    
   275 
   276     OWF_ASSERT(element);
   277     OWF_ASSERT(rect);
   278 
   279     if (rect[0] < 0.0f || rect[1] < 0.0f || rect[2] < 0.0f || rect[3] < 0.0f)
   280     {
   281         result = WFC_ERROR_ILLEGAL_ARGUMENT;
   282     }
   283     else if (WFC_Element_ClampRectangle("source", rect))
   284     {
   285         result = WFC_ERROR_NONE;
   286     }
   287     return result;
   288 }
   289 
   290 /*---------------------------------------------------------------------------
   291  *
   292  *----------------------------------------------------------------------------*/
   293 static WFCErrorCode
   294 WFC_Element_ValidateDestinationRectangle(WFC_ELEMENT* element,
   295                                          WFCfloat* rect)
   296 {
   297     WFCErrorCode            result = WFC_ERROR_NONE;
   298 
   299 #ifndef DEBUG
   300     (void) element;
   301 #endif    
   302     
   303     OWF_ASSERT(element);
   304     OWF_ASSERT(rect);
   305 
   306     DPRINT(("WFC_Element_ValidateDestinationRectangle(element = %d)",
   307             element->handle));
   308 
   309     if (rect[2] < 0.0f || rect[3] < 0.0f)
   310     {
   311         result = WFC_ERROR_ILLEGAL_ARGUMENT;
   312     }
   313     else if (WFC_Element_ClampRectangle("destination", rect))
   314     {
   315         /* ... return error or something here? */
   316         result = WFC_ERROR_NONE;
   317     }
   318 
   319     /* Hmm.. let's clamp the rectangle even more! To 16k*16k at max;
   320      * in OWF_Image_Create we calculate the byte size of the image buffer
   321      * required, and if we have 4bpp, we get overflow for pixelcounts
   322      * >= 65536*16384. */
   323     rect[2] = CLAMP(rect[2], 0, 16384);
   324     rect[3] = CLAMP(rect[3], 0, 16384);
   325 
   326     return result;
   327 }
   328 
   329 #define BOOLEAN_TO_ERROR(x) ((x) ? WFC_ERROR_NONE : WFC_ERROR_ILLEGAL_ARGUMENT)
   330 
   331 /*---------------------------------------------------------------------------
   332  *
   333  *----------------------------------------------------------------------------*/
   334 static WFCErrorCode
   335 WFC_Element_ValidateScalarAttributei(WFC_ELEMENT* element,
   336                                      WFCElementAttrib attrib,
   337                                      WFCint value)
   338 {
   339     WFCErrorCode            result = WFC_ERROR_NONE;
   340 
   341     OWF_ASSERT(element);
   342 
   343     switch (attrib)
   344     {
   345         case WFC_ELEMENT_SOURCE:
   346         {
   347             WFC_IMAGE_PROVIDER* source;
   348 
   349             source = WFC_Device_FindImageProvider(element->device,
   350                                                   value,
   351                                                   WFC_IMAGE_SOURCE);
   352 
   353             result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
   354                                       ((WFC_INVALID_HANDLE != value) &&
   355                                        (NULL != source)));
   356             break;
   357         }
   358 
   359         case WFC_ELEMENT_MASK:
   360         {
   361             WFC_IMAGE_PROVIDER* mask;
   362 
   363             mask = WFC_Device_FindImageProvider(element->device,
   364                                                 value,
   365                                                 WFC_IMAGE_MASK);
   366 
   367             result = BOOLEAN_TO_ERROR((WFC_INVALID_HANDLE == value) ||
   368                                       ((WFC_INVALID_HANDLE != value) &&
   369                                        (NULL != mask)));
   370             break;
   371         }
   372 
   373         case WFC_ELEMENT_SOURCE_ROTATION:
   374         {
   375             WFCRotation rotation = (WFCRotation) value;
   376 
   377             result = BOOLEAN_TO_ERROR((WFC_ROTATION_0    == rotation ||
   378                                        WFC_ROTATION_90   == rotation ||
   379                                        WFC_ROTATION_180  == rotation ||
   380                                        WFC_ROTATION_270  == rotation));
   381             break;
   382         }
   383 
   384         case WFC_ELEMENT_SOURCE_SCALE_FILTER:
   385         {
   386             WFCScaleFilter  filter = (WFCScaleFilter) value;
   387 
   388             result = BOOLEAN_TO_ERROR((WFC_SCALE_FILTER_NONE     == filter ||
   389                                        WFC_SCALE_FILTER_FASTER   == filter ||
   390                                        WFC_SCALE_FILTER_BETTER   == filter));
   391             break;
   392         }
   393 
   394         case WFC_ELEMENT_SOURCE_FLIP:
   395         {
   396             result = WFC_ERROR_NONE;
   397             break;
   398         }
   399 
   400         case WFC_ELEMENT_TRANSPARENCY_TYPES:
   401         {
   402             WFCint          ii;
   403             WFCint          count = sizeof(validTransparencyModes) /
   404                                     sizeof(WFCbitfield);
   405             WFCbitfield     types = (WFCbitfield) value;
   406 
   407             result = WFC_ERROR_ILLEGAL_ARGUMENT;
   408             for (ii = 0; ii < count; ii++) {
   409                 if (types == validTransparencyModes[ii])
   410                 {
   411                     result = WFC_ERROR_NONE;
   412                     break;
   413                 }
   414             }
   415             break;
   416         }
   417 
   418         default:
   419         {
   420             result = WFC_ERROR_BAD_ATTRIBUTE;
   421             break;
   422         }
   423     }
   424     return result;
   425 }
   426 
   427 /*---------------------------------------------------------------------------
   428  *
   429  *----------------------------------------------------------------------------*/
   430 static WFCErrorCode
   431 WFC_Element_ValidateScalarAttributef(WFC_ELEMENT* element,
   432                                      WFCElementAttrib attrib,
   433                                      WFCfloat value)
   434 {
   435     WFCErrorCode          result = WFC_ERROR_NONE;
   436 
   437 #ifndef DEBUG
   438     (void) element;
   439 #endif
   440     
   441     OWF_ASSERT(element);
   442 
   443     switch (attrib)
   444     {
   445         case WFC_ELEMENT_GLOBAL_ALPHA:
   446         {
   447             result = BOOLEAN_TO_ERROR(value >= OWF_ALPHA_MIN_VALUE &&
   448                                       value <= OWF_ALPHA_MAX_VALUE);
   449             break;
   450         }
   451 
   452         /* SPECIAL CASES */
   453         case WFC_ELEMENT_SOURCE_FLIP:
   454         case WFC_ELEMENT_SOURCE_ROTATION:
   455         case WFC_ELEMENT_SOURCE_SCALE_FILTER:
   456         case WFC_ELEMENT_TRANSPARENCY_TYPES:
   457         case WFC_ELEMENT_SOURCE:
   458         case WFC_ELEMENT_MASK:
   459         {
   460             /* NOTE! special early out here. */
   461             result = WFC_ERROR_BAD_ATTRIBUTE;
   462             break;
   463         }
   464 
   465         default:
   466         {
   467             result = WFC_ERROR_ILLEGAL_ARGUMENT;
   468             break;
   469         }
   470     }
   471 
   472     return result;
   473 }
   474 
   475 /*---------------------------------------------------------------------------
   476  *
   477  *----------------------------------------------------------------------------*/
   478 static void
   479 WFC_Element_SetElementImageProvider(WFC_ELEMENT* element,
   480                                     WFC_IMAGE_PROVIDER_TYPE type,
   481                                     WFCHandle handle)
   482 {
   483     WFC_IMAGE_PROVIDER*     provider;
   484 
   485     OWF_ASSERT(element);
   486 
   487     provider = WFC_Device_FindImageProvider(element->device, handle, type);
   488 
   489     switch (type)
   490     {
   491         case WFC_IMAGE_SOURCE:
   492         {
   493             DESTROY(element->cachedSource);
   494             ADDREF(element->cachedSource, provider);
   495             element->sourceHandle = handle;
   496             break;
   497         }
   498         case WFC_IMAGE_MASK:
   499         {
   500             DESTROY(element->cachedMask);
   501             ADDREF(element->cachedMask, provider);
   502             element->maskHandle = handle;
   503             break;
   504         }
   505     }
   506 }
   507 
   508 /*---------------------------------------------------------------------------
   509  *  \brief Set vector integer attribute for an element
   510  *
   511  *  \param element          Element
   512  *  \param attrib           Attribute name
   513  *  \param count            Attribute size
   514  *  \param values           Attribute vector value
   515  *
   516  *----------------------------------------------------------------------------*/
   517 OWF_API_CALL WFCErrorCode
   518 WFC_Element_SetAttribiv(WFC_ELEMENT* element,
   519                         WFCElementAttrib attrib,
   520                         WFCint count,
   521                         const WFCint* values)
   522 {
   523     WFCErrorCode            result = WFC_ERROR_NONE;
   524 
   525 
   526     FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
   527 
   528     switch (attrib)
   529     {
   530         /* Vector attributes */
   531         case WFC_ELEMENT_SOURCE_RECTANGLE:
   532         case WFC_ELEMENT_DESTINATION_RECTANGLE:
   533         {
   534             WFCfloat                rect[4];
   535 
   536             rect[0] = values[0];
   537             rect[1] = values[1];
   538             rect[2] = values[2];
   539             rect[3] = values[3];
   540 
   541             result = WFC_Element_SetAttribfv(element, attrib, count, rect);
   542             break;
   543         }
   544 
   545         case WFC_ELEMENT_GLOBAL_ALPHA:
   546         {
   547             WFCfloat    fvalue = values[0] /
   548                                  (WFCfloat) OWF_BYTE_MAX_VALUE;
   549 
   550             result = WFC_Element_SetAttribfv(element,
   551                                              attrib,
   552                                              1,
   553                                              &fvalue);
   554             break;
   555         }
   556 
   557         /* Scalar attributes */
   558         default:
   559         {
   560             WFCint          value;
   561 
   562             FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
   563 
   564             value = values[0];
   565 
   566             /* Validate the value thus ensuring it is safe to change it */
   567             result = WFC_Element_ValidateScalarAttributei(element,
   568                                                           attrib,
   569                                                           value);
   570             if (WFC_ERROR_NONE != result)
   571             {
   572                 break;
   573             }
   574 
   575             switch (attrib)
   576             {
   577                 case WFC_ELEMENT_SOURCE:
   578                 {
   579                     WFC_Element_SetElementImageProvider(element,
   580                                                         WFC_IMAGE_SOURCE,
   581                                                         value);
   582                     break;
   583                 }
   584                 case WFC_ELEMENT_MASK:
   585                 {
   586                     WFC_Element_SetElementImageProvider(element,
   587                                                         WFC_IMAGE_MASK,
   588                                                         value);
   589                     break;
   590                 }
   591                 case WFC_ELEMENT_SOURCE_FLIP:
   592                 {
   593                     element->sourceFlip = (WFCboolean)value;
   594                     break;
   595                 }
   596                 case WFC_ELEMENT_SOURCE_ROTATION:
   597                 {
   598                     element->sourceRotation = (WFCRotation)value;
   599                     break;
   600                 }
   601                 case WFC_ELEMENT_SOURCE_SCALE_FILTER:
   602                 {
   603                     element->sourceScaleFilter = (WFCScaleFilter)value;
   604                     break;
   605                 }
   606                 case WFC_ELEMENT_TRANSPARENCY_TYPES:
   607                 {
   608                     element->transparencyTypes = value;
   609                     break;
   610                 }
   611                 default:
   612                 {
   613                     result = WFC_ERROR_BAD_ATTRIBUTE;
   614                     break;
   615                 }
   616             }
   617             break;
   618         }
   619     }
   620 
   621     return result;
   622 }
   623 
   624 /*---------------------------------------------------------------------------
   625  *
   626  *----------------------------------------------------------------------------*/
   627 OWF_API_CALL WFCErrorCode
   628 WFC_Element_SetAttribfv(WFC_ELEMENT* element,
   629                         WFCElementAttrib attrib,
   630                         WFCint count,
   631                         const WFCfloat* values)
   632 {
   633     WFCErrorCode            result = WFC_ERROR_NONE;
   634 
   635     FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
   636 
   637     switch (attrib)
   638     {
   639         /* Vector attributes */
   640         case WFC_ELEMENT_SOURCE_RECTANGLE:
   641         case WFC_ELEMENT_DESTINATION_RECTANGLE:
   642         {
   643             WFCfloat        clamped[4];
   644 
   645             FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
   646 
   647             memcpy(clamped, values, 4 * sizeof(WFCfloat));
   648 
   649             if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
   650             {
   651                 /* this clamps the rectangle, in case it has values that
   652                  * cause precision loss or other fuzzy behaviour. */
   653                 result = WFC_Element_ValidateSourceRectangle(element, clamped);
   654 
   655                 if (WFC_ERROR_NONE == result)
   656                 {
   657                     memcpy(element->srcRect, clamped, 4 * sizeof(WFCfloat));
   658 
   659                     DPRINT(("  Source rectangle set to (%.2f,%.2f,%.2f,%.2f)",
   660                             clamped[0], clamped[1], clamped[2], clamped[3]));
   661                 }
   662                 else
   663                 {
   664                     DPRINT(("  Source rectangle (%.2f,%.2f,%.2f,%.2f) is " \
   665                             "invalid",
   666                             values[0], values[1], values[2], values[3]));
   667                 }
   668             }
   669             else
   670             {
   671                 result = WFC_Element_ValidateDestinationRectangle(element,
   672                                                                   clamped);
   673                 if (WFC_ERROR_NONE == result)
   674                 {
   675                     memcpy(element->dstRect, clamped, 4 * sizeof(WFCfloat));
   676 
   677                     DPRINT(("  Destination rectangle set to " \
   678                             "(%.2f,%.2f,%.2f,%.2f)",
   679                             clamped[0], clamped[1], clamped[2], clamped[3]));
   680                 }
   681                 else
   682                 {
   683                     DPRINT(("  Destination rectangle (%.2f,%.2f,%.2f,%.2f) is "
   684                             "invalid",
   685                             values[0], values[1], values[2], values[3]));
   686                 }
   687             }
   688             break;
   689         }
   690 
   691         /* scalar attributes */
   692         case WFC_ELEMENT_GLOBAL_ALPHA:
   693         {
   694             /* values[0] must be [0, 1] */
   695             WFCfloat        value = values[0];
   696 
   697             /* value is [0, 1] map to [0, OWF_ALPHA_MAX] */
   698             value = value * OWF_ALPHA_MAX_VALUE;
   699 
   700             /* validate the value */
   701             result = WFC_Element_ValidateScalarAttributef(element,
   702                                                           attrib,
   703                                                           value);
   704 
   705             if (WFC_ERROR_NONE != result)
   706             {
   707                 /* invalid value for attribute, out we go */
   708                 break;
   709             }
   710 
   711             element->globalAlpha = value;
   712             break;
   713         }
   714 
   715         default:
   716         {
   717             result = WFC_ERROR_BAD_ATTRIBUTE;
   718             break;
   719         }
   720     }
   721 
   722     return result;
   723 }
   724 
   725 /*---------------------------------------------------------------------------
   726  * Attribute getters
   727  *----------------------------------------------------------------------------*/
   728 OWF_API_CALL WFCErrorCode
   729 WFC_Element_GetAttribiv(WFC_ELEMENT* element,
   730                         WFCElementAttrib attrib,
   731                         WFCint count,
   732                         WFCint* values)
   733 {
   734     WFCErrorCode            result = WFC_ERROR_NONE;
   735 
   736 
   737     FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
   738 
   739     switch (attrib)
   740     {
   741         /* Vector attributes */
   742         case WFC_ELEMENT_SOURCE_RECTANGLE:
   743         case WFC_ELEMENT_DESTINATION_RECTANGLE:
   744         {
   745             WFCfloat        rect[4] = {0.0, 0.0, 0.0, 0.0};
   746 
   747             result = WFC_Element_GetAttribfv(element, attrib, count, rect);
   748 
   749             if (WFC_ERROR_NONE == result)
   750             {
   751                 values[0] = floor(rect[0]);
   752                 values[1] = floor(rect[1]);
   753                 values[2] = floor(rect[2]);
   754                 values[3] = floor(rect[3]);
   755             }
   756             break;
   757         }
   758 
   759         /* Scalar attributes */
   760         default:
   761         {
   762             FAIL_IF(1 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
   763 
   764             switch (attrib)
   765             {
   766                 /* pure int attributes */
   767                 case WFC_ELEMENT_SOURCE:
   768                 {
   769                     *values = element->sourceHandle;
   770                     break;
   771                 }
   772                 case WFC_ELEMENT_MASK:
   773                 {
   774                     *values = element->maskHandle;
   775                     break;
   776                 }
   777                 case WFC_ELEMENT_SOURCE_FLIP:
   778                 {
   779                     *values = element->sourceFlip;
   780                     break;
   781                 }
   782                 case WFC_ELEMENT_SOURCE_ROTATION:
   783                 {
   784                     *values = element->sourceRotation;
   785                     break;
   786                 }
   787                 case WFC_ELEMENT_SOURCE_SCALE_FILTER:
   788                 {
   789                     *values = element->sourceScaleFilter;
   790                     break;
   791                 }
   792                 case WFC_ELEMENT_TRANSPARENCY_TYPES:
   793                 {
   794                     *values = element->transparencyTypes;
   795                     break;
   796                 }
   797                 case WFC_ELEMENT_GLOBAL_ALPHA:
   798                 {
   799                     WFCfloat    fvalue;
   800 
   801                     WFC_Element_GetAttribfv(element, attrib, 1, &fvalue);
   802                     *values = floor(OWF_BYTE_MAX_VALUE * fvalue /
   803                                     OWF_ALPHA_MAX_VALUE);
   804                     break;
   805                 }
   806                 default:
   807                 {
   808                     result = WFC_ERROR_BAD_ATTRIBUTE;
   809                     break;
   810                 }
   811             }
   812             break;
   813         }
   814     }
   815 
   816     return result;
   817 }
   818 
   819 /*---------------------------------------------------------------------------
   820  *
   821  *----------------------------------------------------------------------------*/
   822 OWF_API_CALL WFCErrorCode
   823 WFC_Element_GetAttribfv(WFC_ELEMENT* element,
   824                         WFCElementAttrib attrib,
   825                         WFCint count,
   826                         WFCfloat* values)
   827 {
   828     WFCErrorCode            result = WFC_ERROR_NONE;
   829 
   830     FAIL_IF(NULL == values, WFC_ERROR_ILLEGAL_ARGUMENT);
   831 
   832     switch (attrib)
   833     {
   834         /* Vector attributes */
   835         case WFC_ELEMENT_SOURCE_RECTANGLE:
   836         case WFC_ELEMENT_DESTINATION_RECTANGLE:
   837         {
   838             FAIL_IF(4 != count, WFC_ERROR_ILLEGAL_ARGUMENT);
   839 
   840             if (WFC_ELEMENT_SOURCE_RECTANGLE == attrib)
   841             {
   842                 values[0] = element->srcRect[0];
   843                 values[1] = element->srcRect[1];
   844                 values[2] = element->srcRect[2];
   845                 values[3] = element->srcRect[3];
   846             }
   847             else
   848             {
   849                 values[0] = element->dstRect[0];
   850                 values[1] = element->dstRect[1];
   851                 values[2] = element->dstRect[2];
   852                 values[3] = element->dstRect[3];
   853             }
   854             break;
   855         }
   856 
   857         /* Scalar attributes */
   858         default:
   859         {
   860             switch (attrib)
   861             {
   862                 case WFC_ELEMENT_GLOBAL_ALPHA:
   863                 {
   864                     *values = element->globalAlpha;
   865                     break;
   866                 }
   867                 default:
   868                 {
   869                     result = WFC_ERROR_BAD_ATTRIBUTE;
   870                     break;
   871                 }
   872             }
   873             break;
   874         }
   875     }
   876 
   877     return result;
   878 }
   879 
   880 /*---------------------------------------------------------------------------
   881  *  Attribute checkers to use during commit to check element
   882  *  for inconsistencies.
   883  *----------------------------------------------------------------------------*/
   884 static WFCboolean
   885 WFC_Element_CheckAttribute(WFC_ELEMENT* element,
   886                            WFCElementAttrib attrib)
   887 {
   888 #define VALIDATE_SCALAR_I(v)    \
   889     (WFC_Element_ValidateScalarAttributei(element, attrib, v) == \
   890             WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
   891 #define VALIDATE_SCALAR_F(v)    \
   892     (WFC_Element_ValidateScalarAttributef(element, attrib, v) == \
   893             WFC_ERROR_NONE ? WFC_TRUE : WFC_FALSE)
   894 
   895     WFCboolean              result = WFC_TRUE;
   896 
   897     DPRINT(("WFC_Element_CheckAttribute(%08x,%0x)",
   898            element, attrib));
   899 
   900     switch (attrib)
   901     {
   902         /*
   903         INTEGER-ATTRIBUTES
   904         */
   905         case WFC_ELEMENT_SOURCE:
   906         {
   907             /* Validated when the attribute was modified */
   908             break;
   909         }
   910 
   911         case WFC_ELEMENT_MASK:
   912         {
   913             /* Validated when the attribute was modified */
   914             break;
   915         }
   916 
   917         case WFC_ELEMENT_SOURCE_FLIP:
   918         {
   919             result = VALIDATE_SCALAR_I(element->sourceFlip) ? WFC_TRUE: WFC_FALSE;
   920             if (!result)
   921             {
   922                 DPRINT(("  Element source flipping is invalid (%d)",
   923                         element->sourceFlip));
   924             }
   925             break;
   926         }
   927 
   928         case WFC_ELEMENT_SOURCE_ROTATION:
   929         {
   930             result = VALIDATE_SCALAR_I(element->sourceRotation) ? WFC_TRUE: WFC_FALSE;
   931 
   932             if (!result)
   933             {
   934                 DPRINT(("  Element source rotation is invalid (%d)",
   935                         element->sourceRotation));
   936             }
   937             break;
   938         }
   939 
   940         case WFC_ELEMENT_SOURCE_SCALE_FILTER:
   941         {
   942             result = VALIDATE_SCALAR_I(element->sourceScaleFilter) ? WFC_TRUE: WFC_FALSE;
   943 
   944             if (!result)
   945             {
   946                 DPRINT(("  Element source scale filter is invalid (%d)",
   947                         element->sourceScaleFilter));
   948             }
   949             break;
   950         }
   951 
   952         case WFC_ELEMENT_TRANSPARENCY_TYPES:
   953         {
   954             result = VALIDATE_SCALAR_I(element->transparencyTypes) ? WFC_TRUE: WFC_FALSE;
   955 
   956             if (!result)
   957             {
   958                 DPRINT(("  Element transparency type is invalid (%x)",
   959                         element->transparencyTypes));
   960             }
   961             break;
   962         }
   963 
   964         case WFC_ELEMENT_GLOBAL_ALPHA:
   965         {
   966             result = VALIDATE_SCALAR_F(element->globalAlpha) ? WFC_TRUE: WFC_FALSE;
   967             if (!result)
   968             {
   969                 DPRINT(("  Element global alpha is invalid (%d)",
   970                         element->globalAlpha));
   971             }
   972             break;
   973         }
   974 
   975         case WFC_ELEMENT_DESTINATION_RECTANGLE:
   976         {
   977             WFC_IMAGE_PROVIDER* mask;
   978 
   979             /* The <0 test is repeated in SetAttribfv ValidateDestinationRectangle */
   980            if (element->dstRect[2] < 0 || element->dstRect[3] < 0)
   981             {
   982                 DPRINT(("  Element destination rectangle has negative "
   983                         "width/height"));
   984                 result = WFC_FALSE;
   985                 break;
   986             }
   987             if (element->maskHandle!=WFC_INVALID_HANDLE)
   988             {
   989                 result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_MASK);
   990 
   991                 if (result)
   992                 {
   993                     mask = WFC_Device_FindMask(element->device,
   994                                                element->maskHandle);
   995                     if (!mask)
   996                     {
   997                         DPRINT(("  Mask handle is valid, but mask object now destroyed"));
   998                         mask=element->cachedMask;
   999                         if (!mask)
  1000                         {
  1001                             mask=element->mask;
  1002                         }
  1003                     }
  1004                     if (mask)
  1005                     {
  1006                         WFCint  maskWidth, maskHeight;
  1007     
  1008                         DPRINT(("  Element has a mask"));
  1009                         /* if the element has a mask, then width & height must match
  1010                            the dimensions of that mask */
  1011                         owfNativeStreamGetHeader(mask->streamHandle,&maskWidth, &maskHeight,NULL,NULL,NULL);
  1012     
  1013                         if (element->dstRect[2] != maskWidth ||
  1014                             element->dstRect[3] != maskHeight)
  1015                         {
  1016                             DPRINT(("  Mask size (%dx%d) != element size (%d,%d)",
  1017                                    maskWidth, maskHeight,
  1018                                    (int)element->dstRect[2],
  1019                                    (int)element->dstRect[3]));
  1020                             result = WFC_FALSE;
  1021                             break;
  1022                         }
  1023                     }
  1024                     else 
  1025                     {
  1026                         DPRINT(("  No mask pointers could be opened! Scene not safe!"));
  1027                         result = WFC_FALSE;
  1028                     }
  1029                 }
  1030             }
  1031             break;
  1032         }
  1033 
  1034         case WFC_ELEMENT_SOURCE_RECTANGLE:
  1035         {
  1036             WFC_IMAGE_PROVIDER* source;
  1037 
  1038             result = WFC_Element_CheckAttribute(element, WFC_ELEMENT_SOURCE);
  1039             
  1040             if (result && element->sourceHandle!=WFC_INVALID_HANDLE)
  1041             {   /* no source is valid - the element "will not affect composition results" */
  1042                 source = WFC_Device_FindImageProvider(element->device,
  1043                                                       element->sourceHandle,
  1044                                                       WFC_IMAGE_SOURCE);
  1045     
  1046                 result = WFC_TRUE;
  1047                 if (!source)
  1048                 {
  1049                     DPRINT(("  Source handle is valid, but source object now destroyed"));
  1050                     source=element->cachedSource;
  1051                     if (!source)
  1052                     {
  1053                         source=element->source;
  1054                     }
  1055                 }
  1056                 
  1057                 if (source)
  1058                 {
  1059                     WFCint  sourceWidth, sourceHeight;
  1060     
  1061                     owfNativeStreamGetHeader(source->streamHandle,&sourceWidth, &sourceHeight,NULL,NULL,NULL);
  1062                     /* The <0 test is repeated in SetAttribfv ValidateSourceRectangle */ 
  1063                     if ((element->srcRect[0] < 0) ||
  1064                         (element->srcRect[1] < 0) ||
  1065                         (element->srcRect[2] < 0) ||
  1066                         (element->srcRect[3] < 0) ||
  1067                         (element->srcRect[0] + element->srcRect[2]) > sourceWidth ||
  1068                         (element->srcRect[1] + element->srcRect[3]) > sourceHeight)
  1069                     {
  1070                         DPRINT(("  Source rectangle out of bounds"));
  1071                         DPRINT(("  (%f,%f,%f,%f), source size %dx%d",
  1072                                element->srcRect[0], element->srcRect[1],
  1073                                element->srcRect[2], element->srcRect[3],
  1074                                sourceWidth, sourceHeight));
  1075                         result = WFC_FALSE;
  1076                         break;
  1077                     }
  1078                 }
  1079                 else
  1080                 {
  1081                     DPRINT(("  No source pointers could be opened! Scene not safe!"));
  1082                     result = WFC_FALSE;
  1083                 }
  1084             }
  1085             break;
  1086         }
  1087 
  1088         case WFC_ELEMENT_FORCE_32BIT:
  1089         {
  1090             /* to keep compiler happy */
  1091             OWF_ASSERT(0);
  1092             break;
  1093         }
  1094     }
  1095 
  1096     return result;
  1097 
  1098 #undef VALIDATE_SCALAR_F
  1099 #undef VALIDATE_SCALAR_I
  1100 }
  1101 
  1102 /*---------------------------------------------------------------------------
  1103  *
  1104  *----------------------------------------------------------------------------*/
  1105 OWF_API_CALL WFCboolean
  1106 WFC_Element_HasConflicts(WFC_ELEMENT* element)
  1107 {
  1108 #define CHECK(x) \
  1109     if (!WFC_Element_CheckAttribute(element, x)) \
  1110     {\
  1111         DPRINT(("Element %d: Conflict in attribute %08x", element->handle, x));\
  1112         return WFC_TRUE; \
  1113     }
  1114 
  1115     CHECK(WFC_ELEMENT_SOURCE);
  1116     CHECK(WFC_ELEMENT_MASK);
  1117     CHECK(WFC_ELEMENT_SOURCE_RECTANGLE);
  1118     CHECK(WFC_ELEMENT_DESTINATION_RECTANGLE);
  1119     CHECK(WFC_ELEMENT_SOURCE_FLIP);
  1120     CHECK(WFC_ELEMENT_SOURCE_ROTATION);
  1121     CHECK(WFC_ELEMENT_SOURCE_SCALE_FILTER);
  1122     CHECK(WFC_ELEMENT_TRANSPARENCY_TYPES);
  1123     CHECK(WFC_ELEMENT_GLOBAL_ALPHA);
  1124 
  1125 #undef CHECK
  1126 
  1127     /* all ok, no conflicts */
  1128     return WFC_FALSE;
  1129 }
  1130 
  1131 /*---------------------------------------------------------------------------
  1132  *
  1133  *----------------------------------------------------------------------------*/
  1134 OWF_API_CALL WFCboolean
  1135 WFC_Element_AffectsCompositionResults(WFC_ELEMENT* element)
  1136 {
  1137     if (    (element->transparencyTypes&WFC_TRANSPARENCY_ELEMENT_GLOBAL_ALPHA)
  1138        &&   element->globalAlpha==OWF_FULLY_TRANSPARENT )
  1139     {
  1140         return WFC_FALSE;
  1141     }
  1142     if (element->sourceHandle==WFC_INVALID_HANDLE)
  1143     {
  1144         return WFC_FALSE;
  1145     }
  1146     if (element->dstRect[2]==0.0f || element->dstRect[3]==0.0f)
  1147     {
  1148         return WFC_FALSE;
  1149     }
  1150     if (element->srcRect[2]==0.0f || element->srcRect[3]==0.0f)
  1151     {
  1152         return WFC_FALSE;
  1153     }
  1154     return WFC_TRUE;
  1155     
  1156 }
  1157 /*---------------------------------------------------------------------------
  1158  *
  1159  *----------------------------------------------------------------------------*/
  1160 OWF_API_CALL void
  1161 WFC_Element_Commit(WFC_ELEMENT* element)
  1162 {
  1163     OWF_ASSERT(element);
  1164 
  1165     DPRINT(("WFC_Element_Commit(element = %d)\n", element->handle));
  1166 
  1167     /* replace source/mask ONLY if it has changed. without these checks,
  1168      * both source and mask would be overwritten whenever one of them
  1169      * is changed.
  1170      */
  1171 
  1172     if (element->cachedSource != element->source)
  1173     {
  1174         element->source = element->cachedSource;
  1175     }
  1176 
  1177     if (element->cachedMask != element->mask)
  1178     {
  1179         element->mask = element->cachedMask;
  1180     }
  1181 
  1182     /* these must be reset now that the element is committed -- the only purpose
  1183      * of these cached ones is to have source/mask object pointers in the
  1184      * element so that source/mask can be safely deleted from the device even
  1185      * if that particular image provider is set as source/mask for some element
  1186      * that is not yet committed.
  1187      */
  1188 
  1189     DPRINT(("  Prior to destroying cached objects:"));
  1190     DPRINT(("    R(cachedMask) = %d", REFCOUNT(element->cachedMask)));
  1191     DPRINT(("    R(cachedSource) = %d", REFCOUNT(element->cachedSource)));
  1192 
  1193     element->cachedSource = NULL;
  1194     element->cachedMask = NULL;
  1195 
  1196     DPRINT(("  new source   = %d\n", element->source ?
  1197                                      element->source->handle : 0));
  1198     DPRINT(("  new mask     = %d\n", element->mask ?
  1199                                      element->mask->handle : 0));
  1200 }
  1201 
  1202 
  1203 
  1204 #ifdef __cplusplus
  1205 }
  1206 #endif
  1207