コード例 #1
0
        /// <summary>
        /// This function stores just the point data. Coordinates packing algorithm based on the Google/woff2 sources.
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="pointsCapacity"></param>
        /// <param name="pointsLength"></param>
        /// <returns>Returns true on success.</returns>
        private bool PackPoints(WoffIndexer writer, uint pointsCapacity, ref uint pointsLength)
        {
            uint flagOffset  = 0;
            int  lastFlag    = -1;
            int  repeatCount = 0;
            int  lastX       = 0;
            int  lastY       = 0;
            uint xBytes      = 0;
            uint yBytes      = 0;

            int nPoints = _contours.Count;

            for (int i = 0; i < nPoints; ++i)
            {
                var point = _contours[i];
                int flag  = point.IsOnCurve ? kGlyfOnCurve : 0;
                int dx    = point.X - lastX;
                int dy    = point.Y - lastY;
                if (dx == 0)
                {
                    flag |= kGlyfThisXIsSame;
                }
                else if (dx > -256 && dx < 256)
                {
                    flag   |= kGlyfXShort | (dx > 0 ? kGlyfThisXIsSame : 0);
                    xBytes += 1;
                }
                else
                {
                    xBytes += 2;
                }
                if (dy == 0)
                {
                    flag |= kGlyfThisYIsSame;
                }
                else if (dy > -256 && dy < 256)
                {
                    flag   |= kGlyfYShort | (dy > 0 ? kGlyfThisYIsSame : 0);
                    yBytes += 1;
                }
                else
                {
                    yBytes += 2;
                }

                if (flag == lastFlag && repeatCount != 255)
                {
                    writer[flagOffset - 1] |= kGlyfRepeat;
                    repeatCount++;
                }
                else
                {
                    if (repeatCount != 0)
                    {
                        if ((flagOffset >= pointsCapacity))
                        {
                            return(false);
                        }
                        writer[flagOffset++] = (byte)repeatCount;
                    }
                    if ((flagOffset >= pointsCapacity))
                    {
                        return(false);
                    }
                    writer[flagOffset++] = (byte)flag;
                    repeatCount          = 0;
                }
                lastX    = point.X;
                lastY    = point.Y;
                lastFlag = flag;
            }

            if (repeatCount != 0)
            {
                if ((flagOffset >= pointsCapacity))
                {
                    return(false);
                }
                writer[flagOffset++] = (byte)repeatCount;
            }
            uint xyBytes = xBytes + yBytes;

            if ((xyBytes < xBytes || flagOffset + xyBytes < flagOffset || flagOffset + xyBytes > pointsCapacity))
            {
                return(false);
            }

            uint xOffset = flagOffset;
            uint yOffset = flagOffset + xBytes;

            lastX = 0;
            lastY = 0;
            for (int i = 0; i < nPoints; ++i)
            {
                int dx = _contours[i].X - lastX;
                if (dx == 0)
                {
                    // pass
                }
                else if (dx > -256 && dx < 256)
                {
                    writer[xOffset++] = (byte)Math.Abs(dx);
                }
                else
                {
                    // will always fit for valid input, but overflow is harmless
                    writer.WriteInt16(dx, ref xOffset);
                }
                lastX += dx;
                int dy = _contours[i].Y - lastY;
                if (dy == 0)
                {
                    // pass
                }
                else if (dy > -256 && dy < 256)
                {
                    writer[yOffset++] = (byte)Math.Abs(dy);
                }
                else
                {
                    writer.WriteInt16(dy, ref yOffset);
                }
                lastY += dy;
            }
            pointsLength = yOffset;

            return(true);
        }