uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10CurvePath.cpp
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   ?Description
       
    15 *
       
    16 *  Note that we do not use OpenVG's line/arc rendering directly, since the
       
    17 *  curves we are dealing with may have variable widths, which is not supported
       
    18 *  by OpenVG yet. Also, only one opacity factor per path is supported.
       
    19 *
       
    20 */
       
    21 
       
    22 #include "HuiVg10CurvePath.h"
       
    23 #include "HuiVg10Gc.h"
       
    24 #include "uiacceltk/HuiRealPoint.h"
       
    25 #include "uiacceltk/HuiUtil.h"
       
    26 
       
    27 CHuiVg10CurvePath::CHuiVg10CurvePath()
       
    28         : CHuiCurvePath()
       
    29     {
       
    30     }
       
    31     
       
    32     
       
    33 void CHuiVg10CurvePath::ConstructL()
       
    34     {
       
    35     iPathCommands = 0;
       
    36     iLastOpacityFactor = -1.0;
       
    37     iMaxTupleCount = 0;
       
    38     iUsedTupleCount = 0;
       
    39     iPathCoords = 0;
       
    40 
       
    41     iPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 
       
    42                          1.0f, 0.0f, 32, 32, VG_PATH_CAPABILITY_APPEND_TO);
       
    43     HUI_VG_INVARIANT();
       
    44     }
       
    45     
       
    46   
       
    47 CHuiVg10CurvePath::~CHuiVg10CurvePath()
       
    48     {
       
    49     Reset();
       
    50     vgDestroyPath(iPath);
       
    51     iPath = 0;
       
    52     HUI_VG_INVARIANT();
       
    53     }
       
    54   
       
    55     
       
    56 void CHuiVg10CurvePath::Reset()
       
    57     {
       
    58     CHuiCurvePath::Reset();
       
    59     ResetPath();
       
    60     }
       
    61 
       
    62 void CHuiVg10CurvePath::ResetPath()
       
    63     {
       
    64     ResetTuples();
       
    65     vgClearPath(iPath, VG_PATH_CAPABILITY_APPEND_TO);
       
    66     HUI_VG_INVARIANT();
       
    67     }
       
    68     
       
    69 void CHuiVg10CurvePath::ResetTuples()
       
    70     {
       
    71     delete[] iPathCoords;
       
    72     delete[] iPathCommands;
       
    73     iPathCoords = 0;
       
    74     iPathCommands = 0;
       
    75     iMaxTupleCount = 0;
       
    76     iUsedTupleCount = 0;
       
    77     }
       
    78 
       
    79 TInt CHuiVg10CurvePath::SegmentTuples(const TSegment& aSegment) const
       
    80     {
       
    81     if(aSegment.iType == ESegmentTypeLine)
       
    82         {
       
    83         return 2;
       
    84         }
       
    85     else if(aSegment.iType == ESegmentTypeArc)
       
    86         {
       
    87         const TReal32 KAnglePerSegment = 5;
       
    88         TInt tuples = Abs(aSegment.iAngleDelta) / KAnglePerSegment + 1;
       
    89         if(tuples < 2)
       
    90             {
       
    91             tuples = 2;
       
    92             }
       
    93         return tuples;
       
    94         }
       
    95     ASSERT(0);
       
    96     return 0;
       
    97     }
       
    98         
       
    99 void CHuiVg10CurvePath::Update(TReal32 aStartPos, TReal32 aEndPos, 
       
   100                                TReal32 aAlphaFactor,
       
   101                                MHuiMappingFunction* aAlphaFunction,
       
   102                                  MHuiMappingFunction* aWidthFunction) __SOFTFP
       
   103     {
       
   104     const TReal32 KEpsilon = .001;
       
   105     if(!GetVisual() && !NeedUpdate() && Abs(iLastOpacityFactor - aAlphaFactor) < KEpsilon)
       
   106         {
       
   107         // No need to update every time the path is drawn.
       
   108         return;
       
   109         }
       
   110 
       
   111     iLastOpacityFactor = aAlphaFactor;        
       
   112     
       
   113     // Allocate enough memory for the path coordinates and commands. This is 
       
   114     // the maximum number of path nodes that can be. If aStartPos and aEndPos are 
       
   115     // somewhere in the middle, a smaller amount of data is generated.
       
   116     TInt tuples = 0;                    
       
   117     TInt i = 0;    
       
   118     for(i = 0; i < SegmentCount(); ++i)
       
   119         {
       
   120         tuples += SegmentTuples(Segment(i)) - 1;
       
   121         }
       
   122         
       
   123     // One extra tuple for the end.        
       
   124     tuples++;
       
   125     
       
   126     TRAPD(err, SetTupleCountL(tuples));
       
   127     if(err != KErrNone)
       
   128         {
       
   129         ResetPath();
       
   130         return;
       
   131         }
       
   132    
       
   133     // Generate commands for the entire path, starting from aStartPos
       
   134     // and stopping at aEndPos.
       
   135     TReal32 pos = 0;
       
   136     iUsedTupleCount = 0;
       
   137     
       
   138     for(i = 0; i < SegmentCount(); ++i)
       
   139         {
       
   140         const TSegment& segment = Segment(i);
       
   141         TReal32 segmentEnd = pos + segment.iLength;
       
   142         
       
   143         if(aStartPos > segmentEnd)
       
   144             {
       
   145             // The start is past the end of the segment.
       
   146             continue;
       
   147             }            
       
   148         if(aEndPos < pos)
       
   149             {
       
   150             // We're past the end!
       
   151             break;
       
   152             }
       
   153             
       
   154         TReal32 start = pos;
       
   155         TReal32 end = segmentEnd;
       
   156         TBool isFinal = EFalse;        
       
   157         
       
   158         if(start < aStartPos)
       
   159             {
       
   160             start = aStartPos;
       
   161             }
       
   162         if(end >= aEndPos || i == SegmentCount() - 1)
       
   163             {
       
   164             end = aEndPos;
       
   165             isFinal = ETrue;
       
   166             }
       
   167         else
       
   168             {
       
   169             isFinal = EFalse;
       
   170             }                   
       
   171             
       
   172         // Normalize.
       
   173         start -= pos;
       
   174         end -= pos;
       
   175             
       
   176         MakeSegmentTuples(segment, start, end, isFinal, aAlphaFactor, 
       
   177                           aAlphaFunction, aWidthFunction);
       
   178         
       
   179         pos += segment.iLength;
       
   180         }
       
   181     ASSERT(iUsedTupleCount <= iMaxTupleCount);
       
   182     ASSERT(iUsedTupleCount > 0);
       
   183 
       
   184     // First traverse the curve from start to end 
       
   185     vgAppendPathData(iPath, iUsedTupleCount, iPathCommands, iPathCoords);
       
   186     HUI_VG_INVARIANT();
       
   187    
       
   188     // And then back again on the other side
       
   189     TInt tailIndex = 2 * iMaxTupleCount - iUsedTupleCount;
       
   190     vgAppendPathData(iPath, iUsedTupleCount, &iPathCommands[tailIndex], &iPathCoords[2 * tailIndex]);
       
   191     HUI_VG_INVARIANT();
       
   192 
       
   193     // We do not need the tuple arrays anymore so we can free them
       
   194     ResetTuples();
       
   195     
       
   196     CHuiCurvePath::Update(aStartPos, aEndPos, aAlphaFactor, 
       
   197                           aAlphaFunction, aWidthFunction);
       
   198     }
       
   199 
       
   200 void CHuiVg10CurvePath::SetTupleCountL(TInt aTupleCount)
       
   201     {
       
   202     if(iMaxTupleCount != aTupleCount)
       
   203         {
       
   204         ResetPath();
       
   205         
       
   206         // Allocate new arrays.
       
   207         iMaxTupleCount = aTupleCount;
       
   208         
       
   209         if(iMaxTupleCount > 0)
       
   210             {
       
   211             iPathCoords = new (ELeave) VGfloat[2 * iMaxTupleCount * 2];
       
   212             iPathCommands = new (ELeave) VGubyte[iMaxTupleCount * 2];
       
   213 
       
   214             // Since every path command is the same, we can do this at 
       
   215             // allocation time
       
   216             for (TInt i = 0; i < iMaxTupleCount * 2; i++)
       
   217                 {
       
   218                 iPathCommands[i] = VG_LINE_TO;
       
   219                 }
       
   220             }
       
   221         }
       
   222     }
       
   223 
       
   224 void CHuiVg10CurvePath::MakeSegmentTuples(const TSegment& aSegment,
       
   225                                           TReal32 aStart, TReal32 aEnd,
       
   226                                           TBool aIsFinal,
       
   227                                           TReal32 aAlphaFactor,
       
   228                                           MHuiMappingFunction* aAlphaFunction,
       
   229                                           MHuiMappingFunction* aWidthFunction)
       
   230     {
       
   231     // aStart and aEnd are in range [0,length].
       
   232     THuiRealPoint point;
       
   233     THuiRealPoint normal;
       
   234     TReal32 normStart = (aStart + aSegment.iTotalPos) / Length();
       
   235     TReal32 normEnd = (aEnd + aSegment.iTotalPos) / Length(); 
       
   236     
       
   237     if(aSegment.iType == ESegmentTypeLine)
       
   238         {
       
   239         EvaluateSegment(aStart, aSegment, point, &normal);
       
   240         TReal32 width = 1;
       
   241         if(aWidthFunction)
       
   242             {
       
   243             width = aWidthFunction->MapValue(normStart, 0);
       
   244             }
       
   245         TReal32 alpha = 1;
       
   246         if(aAlphaFunction)
       
   247             {
       
   248             alpha = aAlphaFunction->MapValue(normStart, 0);
       
   249             }
       
   250         AddTuple(point, normal, width, alpha * aAlphaFactor);
       
   251         
       
   252         if(aIsFinal)
       
   253             {
       
   254             // Does not reach the end, so we must also make an end tuple.
       
   255             EvaluateSegment(aEnd, aSegment, point, &normal);
       
   256             if(aWidthFunction)
       
   257                 {
       
   258                 width = aWidthFunction->MapValue(normEnd, 0);
       
   259                 }
       
   260             else
       
   261                 {
       
   262                 width = 1;
       
   263                 }
       
   264             if(aAlphaFunction)
       
   265                 {
       
   266                 alpha = aAlphaFunction->MapValue(normEnd, 0);
       
   267                 }
       
   268             else
       
   269                 {                
       
   270                 alpha = 1;
       
   271                 }
       
   272             AddTuple(point, normal, width, alpha * aAlphaFactor);
       
   273             }
       
   274         }
       
   275         
       
   276     if(aSegment.iType == ESegmentTypeArc)
       
   277         {
       
   278         // Make a set of tuples.
       
   279         TInt count = SegmentTuples(aSegment);
       
   280         TInt endCount = count;
       
   281         if(aIsFinal)
       
   282             {
       
   283             endCount = count - 1;
       
   284             }
       
   285         else
       
   286             {
       
   287             count--;
       
   288             endCount--;
       
   289             }
       
   290         
       
   291         for(TInt i = 0; i < count; ++i)
       
   292             {
       
   293             TReal32 off = i / TReal32(endCount);
       
   294             EvaluateSegment(aStart + (aEnd - aStart) * off, aSegment, point, 
       
   295                             &normal);
       
   296             TReal32 width = 1;
       
   297             if(aWidthFunction)
       
   298                 {
       
   299                 width = aWidthFunction->MapValue(normStart + 
       
   300                     (normEnd - normStart) * off, 0);
       
   301                 }
       
   302             TReal32 alpha = 1;
       
   303             if(aAlphaFunction)
       
   304                 {
       
   305                 alpha = aAlphaFunction->MapValue(normStart + 
       
   306                     (normEnd - normStart) * off, 0);
       
   307                 }
       
   308             AddTuple(point, normal, width, alpha * aAlphaFactor);
       
   309             }
       
   310         }
       
   311     }
       
   312 
       
   313 void CHuiVg10CurvePath::AddTuple(const THuiRealPoint& aPoint,
       
   314                                  const THuiRealPoint& aNormal,
       
   315                                  TReal32 aWidth, TReal32 /*aAlpha*/)
       
   316     {
       
   317     ASSERT(iUsedTupleCount < iMaxTupleCount);
       
   318 
       
   319     // Make a pair of vertices. Normal is to the left.
       
   320     //    
       
   321     // The first half of the path goes from the beginning of the curve 
       
   322     // to the end, while the second half traverses the same route 
       
   323     // backwards:
       
   324     //
       
   325     //     0                     iUsedTupleCount
       
   326     //     >--->--->---> ... >---v
       
   327     //     |                     |
       
   328     //     ^---<---<---< ... <---<
       
   329     //     iMaxTupleCount -      iMaxtupleCount
       
   330     //     iUsedTupleCount
       
   331     //
       
   332     // The coordinate array looks like this:
       
   333     //
       
   334     //     +---+---+---+---+---+---+---+---+    N: tuple N left vertex
       
   335     //     | 0 | 1 | 2 | X | X | 2'| 1'| 0'|   N': tuple N right vertex
       
   336     //     +---+---+---+---+---+---+---+---+    X: unused
       
   337     //
       
   338     VGfloat* vertex1 = &iPathCoords[2 * iUsedTupleCount];
       
   339     VGfloat* vertex2 = &iPathCoords[2 * (2 * iMaxTupleCount - iUsedTupleCount - 1)];
       
   340     const CHuiVisual* visual = GetVisual();
       
   341 
       
   342     if (visual)
       
   343         {
       
   344         THuiRealPoint point1(aPoint.iX + aNormal.iX * aWidth/2,aPoint.iY + aNormal.iY * aWidth/2);
       
   345         THuiRealPoint point2(aPoint.iX - aNormal.iX * aWidth/2,aPoint.iY - aNormal.iY * aWidth/2);
       
   346         point1 = visual->LocalPointInPixels(point1);
       
   347         point2 = visual->LocalPointInPixels(point2);  
       
   348         vertex1[0] = point1.iX;
       
   349         vertex1[1] = point1.iY;
       
   350         vertex2[0] = point2.iX;
       
   351         vertex2[1] = point2.iY;
       
   352         }
       
   353     else
       
   354         {
       
   355         vertex1[0] = aPoint.iX + aNormal.iX * aWidth/2;
       
   356         vertex1[1] = aPoint.iY + aNormal.iY * aWidth/2;
       
   357         vertex2[0] = aPoint.iX - aNormal.iX * aWidth/2;
       
   358         vertex2[1] = aPoint.iY - aNormal.iY * aWidth/2;     
       
   359         }
       
   360 
       
   361     iUsedTupleCount++;
       
   362     }
       
   363 
       
   364 void CHuiVg10CurvePath::Draw(const TPoint& aOrigin, CHuiGc* aGc) const
       
   365     {
       
   366     CHuiVg10Gc* gc = static_cast<CHuiVg10Gc*>(aGc);
       
   367     ASSERT(gc);
       
   368     gc->UpdateColor();
       
   369     
       
   370     VGPaint paint = vgGetPaint(VG_FILL_PATH);
       
   371     VGfloat color[4], modifiedColor[4];
       
   372     
       
   373     if (paint != VG_INVALID_HANDLE)
       
   374         {
       
   375         vgGetParameterfv(paint, VG_PAINT_COLOR, 4, color);
       
   376         modifiedColor[0] = color[0];
       
   377         modifiedColor[1] = color[1];
       
   378         modifiedColor[2] = color[2];
       
   379         modifiedColor[3] = iLastOpacityFactor;
       
   380         vgSetParameterfv(paint, VG_PAINT_COLOR, 4, modifiedColor);
       
   381         HUI_VG_INVARIANT();
       
   382         }
       
   383 
       
   384     gc->UpdateMatrix(VG_MATRIX_PATH_USER_TO_SURFACE);
       
   385     vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
       
   386     vgTranslate(aOrigin.iX, aOrigin.iY);
       
   387     vgDrawPath(iPath, VG_FILL_PATH);
       
   388     vgTranslate(-aOrigin.iX, -aOrigin.iY);
       
   389     vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
       
   390 
       
   391     HUI_VG_INVARIANT();
       
   392 
       
   393     if (paint != VG_INVALID_HANDLE)
       
   394         {
       
   395         vgSetParameterfv(paint, VG_PAINT_COLOR, 4, color);
       
   396         HUI_VG_INVARIANT();
       
   397         }
       
   398     }