示例#1
0
        private static PdfFunction ConstructSingleGradientSegmentFunction(GradientColorStop from, GradientColorStop
                                                                          to)
        {
            double exponent = 1d;

            float[] fromColor = from.GetRgbArray();
            float[] toColor   = to.GetRgbArray();
            if (from.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_BETWEEN_COLORS)
            {
                double hintOffset = from.GetHintOffset();
                if (hintOffset <= 0d + ZERO_EPSILON)
                {
                    fromColor = toColor;
                }
                else
                {
                    if (hintOffset >= 1d - ZERO_EPSILON)
                    {
                        toColor = fromColor;
                    }
                    else
                    {
                        // similar to css color hint logic
                        exponent = Math.Log(0.5) / Math.Log(hintOffset);
                    }
                }
            }
            return(new PdfFunction.Type2(new PdfArray(new float[] { 0f, 1f }), null, new PdfArray(fromColor), new PdfArray
                                             (toColor), new PdfNumber(exponent)));
        }
示例#2
0
        private static void NormalizeFirstStopOffset(IList <GradientColorStop> result)
        {
            // assert that all stops has no absolute on vector offsets and hints
            GradientColorStop firstStop = result[0];

            if (firstStop.GetOffsetType() != GradientColorStop.OffsetType.AUTO)
            {
                return;
            }
            double firstStopOffset = 0;

            foreach (GradientColorStop stopColor in result)
            {
                if (stopColor.GetOffsetType() == GradientColorStop.OffsetType.RELATIVE)
                {
                    firstStopOffset = stopColor.GetOffset();
                    break;
                }
                else
                {
                    if (stopColor.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT)
                    {
                        firstStopOffset = stopColor.GetHintOffset();
                        break;
                    }
                }
            }
            firstStopOffset = Math.Min(0, firstStopOffset);
            firstStop.SetOffset(firstStopOffset, GradientColorStop.OffsetType.RELATIVE);
        }
示例#3
0
        private static PdfFunction ConstructFunction(IList <GradientColorStop> toConstruct)
        {
            int functionsAmount = toConstruct.Count - 1;

            double[]            bounds         = new double[functionsAmount - 1];
            IList <PdfFunction> type2Functions = new List <PdfFunction>(functionsAmount);
            GradientColorStop   currentStop;
            GradientColorStop   nextStop = toConstruct[0];
            double domainStart           = nextStop.GetOffset();

            for (int i = 1; i < functionsAmount; ++i)
            {
                currentStop   = nextStop;
                nextStop      = toConstruct[i];
                bounds[i - 1] = nextStop.GetOffset();
                type2Functions.Add(ConstructSingleGradientSegmentFunction(currentStop, nextStop));
            }
            currentStop = nextStop;
            nextStop    = toConstruct[toConstruct.Count - 1];
            type2Functions.Add(ConstructSingleGradientSegmentFunction(currentStop, nextStop));
            double domainEnd = nextStop.GetOffset();

            double[] encode = new double[functionsAmount * 2];
            for (int i = 0; i < encode.Length; i += 2)
            {
                encode[i]     = 0d;
                encode[i + 1] = 1d;
            }
            return(new PdfFunction.Type3(new PdfArray(new double[] { domainStart, domainEnd }), null, type2Functions,
                                         new PdfArray(bounds), new PdfArray(encode)));
        }
示例#4
0
 private static void NormalizeHintsOffsets(IList <GradientColorStop> result)
 {
     // normalize all except last
     for (int i = 0; i < result.Count - 1; ++i)
     {
         GradientColorStop stopColor = result[i];
         if (stopColor.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT)
         {
             double currentStopOffset = stopColor.GetOffset();
             double nextStopOffset    = result[i + 1].GetOffset();
             if (currentStopOffset != nextStopOffset)
             {
                 double hintOffset = (stopColor.GetHintOffset() - currentStopOffset) / (nextStopOffset - currentStopOffset);
                 stopColor.SetHint(hintOffset, GradientColorStop.HintOffsetType.RELATIVE_BETWEEN_COLORS);
             }
             else
             {
                 // if stops has the same offset, then no hint needed
                 stopColor.SetHint(0, GradientColorStop.HintOffsetType.NONE);
             }
         }
     }
     // the last color hint is not needed as even with pad and reflect it won't be used
     result[result.Count - 1].SetHint(0, GradientColorStop.HintOffsetType.NONE);
 }
示例#5
0
 /// <summary>
 /// Adds the new color stop to the end (
 /// <see cref="AbstractLinearGradientBuilder">more info</see>
 /// ).
 /// </summary>
 /// <remarks>
 /// Adds the new color stop to the end (
 /// <see cref="AbstractLinearGradientBuilder">more info</see>
 /// ).
 /// Note: if the previously added color stop's offset would have grater offset than the added
 /// one, then the new offset would be normalized to be equal to the previous one. (Comparison
 /// made between relative on coordinates vector offsets. If any of them has
 /// the absolute offset, then the absolute value would converted to relative first.)
 /// </remarks>
 /// <param name="gradientColorStop">the gradient stop color to add</param>
 /// <returns>the current builder instance</returns>
 public virtual AbstractLinearGradientBuilder AddColorStop(GradientColorStop gradientColorStop)
 {
     if (gradientColorStop != null)
     {
         this.stops.Add(gradientColorStop);
     }
     return(this);
 }
示例#6
0
        public virtual void CornerCasesTest()
        {
            GradientColorStop stopToTest = new GradientColorStop((float[])null, 1.5, GradientColorStop.OffsetType.AUTO
                                                                 ).SetHint(1.5, GradientColorStop.HintOffsetType.NONE);

            NUnit.Framework.Assert.AreEqual(new float[] { 0f, 0f, 0f }, stopToTest.GetRgbArray());
            NUnit.Framework.Assert.AreEqual(0, stopToTest.GetOffset(), 1e-10);
            NUnit.Framework.Assert.AreEqual(GradientColorStop.OffsetType.AUTO, stopToTest.GetOffsetType());
            NUnit.Framework.Assert.AreEqual(0, stopToTest.GetHintOffset(), 1e-10);
            NUnit.Framework.Assert.AreEqual(GradientColorStop.HintOffsetType.NONE, stopToTest.GetHintOffsetType());
        }
示例#7
0
        public virtual void NormalizationTest()
        {
            GradientColorStop stopToTest = new GradientColorStop(new float[] { -0.5f, 1.5f, 0.5f, 0.5f }, 1.5, GradientColorStop.OffsetType
                                                                 .AUTO).SetHint(1.5, GradientColorStop.HintOffsetType.NONE);

            NUnit.Framework.Assert.AreEqual(new float[] { 0f, 1f, 0.5f }, stopToTest.GetRgbArray());
            NUnit.Framework.Assert.AreEqual(0, stopToTest.GetOffset(), 1e-10);
            NUnit.Framework.Assert.AreEqual(GradientColorStop.OffsetType.AUTO, stopToTest.GetOffsetType());
            NUnit.Framework.Assert.AreEqual(0, stopToTest.GetHintOffset(), 1e-10);
            NUnit.Framework.Assert.AreEqual(GradientColorStop.HintOffsetType.NONE, stopToTest.GetHintOffsetType());
        }
示例#8
0
        private static PdfShading.Axial CreateAxialShading(Point[] baseCoordinatesVector, IList <GradientColorStop>
                                                           stops, GradientSpreadMethod spreadMethod, Rectangle targetBoundingBox)
        {
            double baseVectorLength = baseCoordinatesVector[1].Distance(baseCoordinatesVector[0]);
            IList <GradientColorStop> stopsToConstruct = NormalizeStops(stops, baseVectorLength);

            double[] coordinatesDomain = new double[] { 0, 1 };
            Point[]  actualCoordinates;
            if (baseVectorLength < ZERO_EPSILON || stopsToConstruct.Count == 1)
            {
                // single color case
                if (spreadMethod == GradientSpreadMethod.NONE)
                {
                    return(null);
                }
                actualCoordinates = new Point[] { new Point(targetBoundingBox.GetLeft(), targetBoundingBox.GetBottom()), new
                                                  Point(targetBoundingBox.GetRight(), targetBoundingBox.GetBottom()) };
                GradientColorStop lastColorStop = stopsToConstruct[stopsToConstruct.Count - 1];
                stopsToConstruct = JavaUtil.ArraysAsList(new GradientColorStop(lastColorStop, 0d, GradientColorStop.OffsetType
                                                                               .RELATIVE), new GradientColorStop(lastColorStop, 1d, GradientColorStop.OffsetType.RELATIVE));
            }
            else
            {
                coordinatesDomain = EvaluateCoveringDomain(baseCoordinatesVector, targetBoundingBox);
                if (spreadMethod == GradientSpreadMethod.REPEAT || spreadMethod == GradientSpreadMethod.REFLECT)
                {
                    stopsToConstruct = AdjustNormalizedStopsToCoverDomain(stopsToConstruct, coordinatesDomain, spreadMethod);
                }
                else
                {
                    if (spreadMethod == GradientSpreadMethod.PAD)
                    {
                        AdjustStopsForPadIfNeeded(stopsToConstruct, coordinatesDomain);
                    }
                    else
                    {
                        // none case
                        double firstStopOffset = stopsToConstruct[0].GetOffset();
                        double lastStopOffset  = stopsToConstruct[stopsToConstruct.Count - 1].GetOffset();
                        if ((lastStopOffset - firstStopOffset < ZERO_EPSILON) || coordinatesDomain[1] <= firstStopOffset || coordinatesDomain
                            [0] >= lastStopOffset)
                        {
                            return(null);
                        }
                        coordinatesDomain[0] = Math.Max(coordinatesDomain[0], firstStopOffset);
                        coordinatesDomain[1] = Math.Min(coordinatesDomain[1], lastStopOffset);
                    }
                }
                System.Diagnostics.Debug.Assert(coordinatesDomain[0] <= coordinatesDomain[1]);
                actualCoordinates = CreateCoordinatesForNewDomain(coordinatesDomain, baseCoordinatesVector);
            }
            return(new PdfShading.Axial(new PdfDeviceCs.Rgb(), CreateCoordsPdfArray(actualCoordinates), new PdfArray(coordinatesDomain
                                                                                                                     ), ConstructFunction(stopsToConstruct)));
        }
示例#9
0
        private static void NormalizeAutoStops(IList <GradientColorStop> toNormalizeList, int fromIndex, int toIndex
                                               , double prevOffset, double nextOffset)
        {
            System.Diagnostics.Debug.Assert(toIndex >= fromIndex);
            int    intervalsCount = Math.Min(toIndex, toNormalizeList.Count - 1) - fromIndex + 1;
            double offsetShift    = (nextOffset - prevOffset) / intervalsCount;
            double currentOffset  = prevOffset;

            for (int i = fromIndex; i < toIndex; ++i)
            {
                currentOffset += offsetShift;
                GradientColorStop currentAutoStop = toNormalizeList[i];
                System.Diagnostics.Debug.Assert(currentAutoStop.GetOffsetType() == GradientColorStop.OffsetType.AUTO);
                currentAutoStop.SetOffset(currentOffset, GradientColorStop.OffsetType.RELATIVE);
            }
        }
示例#10
0
        private static void AdjustStopsForPadIfNeeded(IList <GradientColorStop> stopsToConstruct, double[] coordinatesDomain
                                                      )
        {
            GradientColorStop firstStop = stopsToConstruct[0];

            if (coordinatesDomain[0] < firstStop.GetOffset())
            {
                stopsToConstruct.Add(0, new GradientColorStop(firstStop, coordinatesDomain[0], GradientColorStop.OffsetType
                                                              .RELATIVE));
            }
            GradientColorStop lastStop = stopsToConstruct[stopsToConstruct.Count - 1];

            if (coordinatesDomain[1] > lastStop.GetOffset())
            {
                stopsToConstruct.Add(new GradientColorStop(lastStop, coordinatesDomain[1], GradientColorStop.OffsetType.RELATIVE
                                                           ));
            }
        }
示例#11
0
        private static IList <GradientColorStop> CopyStopsAndNormalizeAbsoluteOffsets(IList <GradientColorStop> toNormalize
                                                                                      , double baseVectorLength)
        {
            double lastUsedOffset          = double.NegativeInfinity;
            IList <GradientColorStop> copy = new List <GradientColorStop>(toNormalize.Count);

            foreach (GradientColorStop stop in toNormalize)
            {
                double offset = stop.GetOffset();
                GradientColorStop.OffsetType offsetType = stop.GetOffsetType();
                if (offsetType == GradientColorStop.OffsetType.ABSOLUTE)
                {
                    offsetType = GradientColorStop.OffsetType.RELATIVE;
                    offset    /= baseVectorLength;
                }
                if (offsetType == GradientColorStop.OffsetType.RELATIVE)
                {
                    if (offset < lastUsedOffset)
                    {
                        offset = lastUsedOffset;
                    }
                    lastUsedOffset = offset;
                }
                GradientColorStop result     = new GradientColorStop(stop, offset, offsetType);
                double            hintOffset = stop.GetHintOffset();
                GradientColorStop.HintOffsetType hintOffsetType = stop.GetHintOffsetType();
                if (hintOffsetType == GradientColorStop.HintOffsetType.ABSOLUTE_ON_GRADIENT)
                {
                    hintOffsetType = GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT;
                    hintOffset    /= baseVectorLength;
                }
                if (hintOffsetType == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT)
                {
                    if (hintOffset < lastUsedOffset)
                    {
                        hintOffset = lastUsedOffset;
                    }
                    lastUsedOffset = hintOffset;
                }
                result.SetHint(hintOffset, hintOffsetType);
                copy.Add(result);
            }
            return(copy);
        }
示例#12
0
        private static void NormalizeAutoStops(IList <GradientColorStop> toNormalize)
        {
            System.Diagnostics.Debug.Assert(toNormalize[0].GetOffsetType() == GradientColorStop.OffsetType.RELATIVE);
            int firstAutoStopIndex           = 1;
            GradientColorStop firstStopColor = toNormalize[0];
            double            prevOffset     = firstStopColor.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT
                 ? firstStopColor.GetHintOffset() : firstStopColor.GetOffset();

            for (int i = 1; i < toNormalize.Count; ++i)
            {
                GradientColorStop currentStop = toNormalize[i];
                if (currentStop.GetOffsetType() == GradientColorStop.OffsetType.AUTO)
                {
                    if (currentStop.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT)
                    {
                        double hintOffset = currentStop.GetHintOffset();
                        NormalizeAutoStops(toNormalize, firstAutoStopIndex, i + 1, prevOffset, hintOffset);
                        prevOffset         = hintOffset;
                        firstAutoStopIndex = i + 1;
                    }
                }
                else
                {
                    if (firstAutoStopIndex < i)
                    {
                        // current stop offset is relative
                        double offset = currentStop.GetOffset();
                        NormalizeAutoStops(toNormalize, firstAutoStopIndex, i, prevOffset, offset);
                    }
                    firstAutoStopIndex = i + 1;
                    prevOffset         = currentStop.GetHintOffsetType() == GradientColorStop.HintOffsetType.RELATIVE_ON_GRADIENT ? currentStop
                                         .GetHintOffset() : currentStop.GetOffset();
                }
            }
            // check whether the last interval has auto
            if (firstAutoStopIndex < toNormalize.Count)
            {
                double lastStopOffset = Math.Max(1, prevOffset);
                NormalizeAutoStops(toNormalize, firstAutoStopIndex, toNormalize.Count, prevOffset, lastStopOffset);
            }
        }
示例#13
0
        private static IList <GradientColorStop> AdjustNormalizedStopsToCoverDomain(IList <GradientColorStop> normalizedStops
                                                                                    , double[] targetDomain, GradientSpreadMethod spreadMethod)
        {
            IList <GradientColorStop> adjustedStops = new List <GradientColorStop>();
            GradientColorStop         lastColorStop = normalizedStops[normalizedStops.Count - 1];
            double originalIntervalEnd    = lastColorStop.GetOffset();
            double originalIntervalStart  = normalizedStops[0].GetOffset();
            double originalIntervalLength = originalIntervalEnd - originalIntervalStart;

            if (originalIntervalLength <= ZERO_EPSILON)
            {
                return(JavaUtil.ArraysAsList(new GradientColorStop(lastColorStop, targetDomain[0], GradientColorStop.OffsetType
                                                                   .RELATIVE), new GradientColorStop(lastColorStop, targetDomain[1], GradientColorStop.OffsetType.RELATIVE
                                                                                                     )));
            }
            double startIntervalsShift = Math.Floor((targetDomain[0] - originalIntervalStart) / originalIntervalLength
                                                    );
            double iterationOffset    = originalIntervalStart + (originalIntervalLength * startIntervalsShift);
            bool   isIterationInverse = spreadMethod == GradientSpreadMethod.REFLECT && Math.Abs(startIntervalsShift) %
                                        2 != 0;
            int    currentIterationIndex = isIterationInverse ? normalizedStops.Count - 1 : 0;
            double lastComputedOffset    = iterationOffset;

            while (lastComputedOffset <= targetDomain[1])
            {
                GradientColorStop currentStop = normalizedStops[currentIterationIndex];
                lastComputedOffset = isIterationInverse ? iterationOffset + originalIntervalEnd - currentStop.GetOffset() :
                                     iterationOffset + currentStop.GetOffset() - originalIntervalStart;
                GradientColorStop computedStop = new GradientColorStop(currentStop, lastComputedOffset, GradientColorStop.OffsetType
                                                                       .RELATIVE);
                if (lastComputedOffset < targetDomain[0] && !adjustedStops.IsEmpty())
                {
                    adjustedStops[0] = computedStop;
                }
                else
                {
                    adjustedStops.Add(computedStop);
                }
                if (isIterationInverse)
                {
                    --currentIterationIndex;
                    if (currentIterationIndex < 0)
                    {
                        iterationOffset      += originalIntervalLength;
                        isIterationInverse    = false;
                        currentIterationIndex = 1;
                    }
                }
                else
                {
                    ++currentIterationIndex;
                    if (currentIterationIndex == normalizedStops.Count)
                    {
                        iterationOffset      += originalIntervalLength;
                        isIterationInverse    = spreadMethod == GradientSpreadMethod.REFLECT;
                        currentIterationIndex = isIterationInverse ? normalizedStops.Count - 2 : 0;
                    }
                }
                // check the next iteration type to set the correct stop color hint for just added stop
                if (isIterationInverse)
                {
                    GradientColorStop nextColor = normalizedStops[currentIterationIndex];
                    // this method should be invoked only after the normalization. it means that
                    // the hint offset type for each stop is either relative to colors interval
                    // (i.e. for inverse iteration we need to inverse the hint offset), or is none
                    // (i.e. the hint offset value should be ignored)
                    computedStop.SetHint(1 - nextColor.GetHintOffset(), nextColor.GetHintOffsetType());
                }
                else
                {
                    computedStop.SetHint(currentStop.GetHintOffset(), currentStop.GetHintOffsetType());
                }
            }
            return(adjustedStops);
        }