Ejemplo n.º 1
0
        public void Badge_YOffsetTest()
        {
            ScryberBadgeStyle target = new ScryberBadgeStyle();

            // Default value

            PDFUnit expected = ScryberBadgeStyle.DefaultYOffset;
            PDFUnit actual   = target.YOffset;

            Assert.AreEqual(expected, actual);

            // Set Value

            expected       = 20;
            target.YOffset = expected;
            actual         = target.YOffset;
            Assert.AreEqual(expected, actual);

            // Change Value

            expected       = new PDFUnit(100, PageUnits.Points);
            target.YOffset = expected;
            actual         = target.YOffset;
            Assert.AreEqual(expected, actual);

            // Remove Value

            expected = ScryberBadgeStyle.DefaultYOffset;
            target.RemoveYOffset();
            actual = target.YOffset;
            Assert.AreEqual(expected, actual);
        }
        /// <summary>
        /// Lays out all the contents of the list item in the current itemblock and returns the used height of the
        /// components it has laid out.
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        private PDFUnit LayoutItemContent(ListNumberEntry entry)
        {
            ComponentList          contents  = null;
            IPDFContainerComponent container = entry.ListItem as IPDFContainerComponent;

            PDFUnit avail = _itemblock.CurrentRegion.AvailableHeight;

            if (container.HasContent)
            {
                //because we are mimicing being the container - set the full style to the item style
                Style last = this.FullStyle;
                this.FullStyle = entry.FullStyle;

                contents = container.Content;
                this.DoLayoutChildren(contents);

                //And restore the full style to the previous item after.
                this.FullStyle = last;
            }
            this._itemblock.CurrentRegion.CloseCurrentItem();

            // Calculate the height used and return
            PDFUnit newAvail = _itemblock.CurrentRegion.AvailableHeight;
            PDFUnit used     = avail - newAvail;

            return(used);
        }
        //
        // overflow methods
        //

        #region protected virtual bool StartListInAnotherRegion(PDFUnit itemHeight, PDFLayoutBlock item, int itemindex)

        /// <summary>
        /// Closes down the current list and attempts to open a new region to start laying out any further items.
        /// Returns true if a new region was created, otherwise false.
        /// </summary>
        /// <param name="itemHeight"></param>
        /// <param name="item"></param>
        /// <param name="itemindex"></param>
        /// <returns></returns>
        protected virtual bool StartListInAnotherRegion(PDFUnit itemHeight, PDFLayoutBlock item, int itemindex)
        {
            PDFLayoutRegion itemRegion     = item.CurrentRegion;
            PDFLayoutBlock  origListBlock  = item.Parent as PDFLayoutBlock;
            PDFLayoutRegion origListRegion = origListBlock.CurrentRegion;

            if (origListBlock.IsClosed == false)
            {
                origListBlock.Close();
            }
            //(origListBlock.Parent as PDFLayoutBlock).CurrentRegion.AddToSize(origListBlock);

            bool newPage;
            bool started = this.MoveToNextRegion(itemHeight, ref itemRegion, ref item, out newPage);

            if (started)
            {
                if (this.Context.ShouldLogVerbose)
                {
                    this.Context.TraceLog.Add(TraceLevel.Verbose, ListEngineLogCategory, "Started list '" + this.List.ID + "' in a new " + (newPage ? "Page" : "Region") + " and list item block is now '" + item.ToString() + "'");
                }
            }

            return(started);
        }
        //
        // overflow operations
        //


        protected virtual void DoMoveToNextRegion(PDFUnit lineheight)
        {
            PDFLayoutLine lastline = this.CurrentLine;

            this.EndText(); //Always end this block of text

            bool             newPage;
            PDFLayoutRegion  region = lastline.Region;
            PDFLayoutBlock   block  = (PDFLayoutBlock)region.Parent;
            LayoutEngineBase engine = this.Parent as LayoutEngineBase;

            if (null == engine)
            {
                throw new NullReferenceException("Parent engine was not the expected BlockLayoutEngine. A Hack that is needed for overflowing textual content");
            }
            else if (engine.MoveToNextRegion(lineheight, ref region, ref block, out newPage))
            {
                if (!this.StartText())
                {
                    return;
                }
            }
            else
            {
                if (this.Context.TraceLog.ShouldLog(TraceLevel.Message))
                {
                    this.Context.TraceLog.Add(TraceLevel.Message, LOG_CATEGORY, "Cannot layout any more text for component '" + this.TextComponent.ID + "'. Available space full and cannot move to another region.");
                }

                this.ContinueLayout = false;
            }
        }
        public void HorizontalLineFor_Test()
        {
            PDFGraphicsPath target = new PDFGraphicsPath();

            Assert.IsTrue(target.Paths.Count == 1);
            Assert.IsTrue(target.HasCurrentPath);

            Assert.AreEqual(target.Cursor, PDFPoint.Empty);

            PDFPoint pos = new PDFPoint(10, 10);

            target.LineTo(pos);

            Assert.AreEqual(target.Cursor, pos);
            Assert.AreEqual(target.Paths[0].Operations.Count, 1);
            Assert.IsInstanceOfType(target.Paths[0].Operations[0], typeof(PathLineData));
            PathLineData data = (PathLineData)target.Paths[0].Operations[0];

            Assert.AreEqual(data.LineTo, pos);

            PDFUnit h = 40;

            target.HorizontalLineFor(h);

            pos = new PDFPoint(pos.X + h, pos.Y);
            Assert.AreEqual(target.Cursor, pos);
            Assert.AreEqual(target.Paths[0].Operations.Count, 2);
            Assert.IsInstanceOfType(target.Paths[0].Operations[1], typeof(PathLineData));
            data = (PathLineData)target.Paths[0].Operations[1];
            Assert.AreEqual(data.LineTo, pos);
        }
Ejemplo n.º 6
0
        public void Position_YTest()
        {
            PositionStyle target = new PositionStyle();

            // Default value

            PDFUnit expected = PDFUnit.Empty;
            PDFUnit actual   = target.Y;

            Assert.AreEqual(expected, actual);

            // Set Value

            expected = 20;
            target.Y = expected;
            actual   = target.Y;
            Assert.AreEqual(expected, actual);

            // Change Value

            expected = new PDFUnit(120, PageUnits.Millimeters);
            target.Y = expected;
            actual   = target.Y;
            Assert.AreEqual(expected, actual);

            // Remove Value

            expected = PDFUnit.Empty;
            target.RemoveY();
            actual = target.Y;
            Assert.AreEqual(expected, actual);
        }
        protected override bool DoSetStyleValue(Style onStyle, CSSStyleItemReader reader)
        {
            PDFUnit size   = PDFUnit.Zero;
            bool    result = true;

            if (reader.ReadNextValue())
            {
                var value = reader.CurrentTextValue;
                if (IsExpression(value))
                {
                    result = AttachExpressionBindingHandler(onStyle, StyleKeys.TextCharSpacingKey, value, DoConvertLetterSpacing);
                }
                else if (TryGetLetterSpacing(reader.CurrentTextValue, out size))
                {
                    onStyle.SetValue(StyleKeys.TextCharSpacingKey, size);
                    result = true;
                }
            }
            else
            {
                result = false;
            }

            return(result);
        }
Ejemplo n.º 8
0
        protected bool DoConvertOverflowX(StyleBase style, object value, out PDFUnit clipping)
        {
            if (null == value)
            {
                clipping = PDFUnit.Empty;
                return(false);
            }
            else if (TryParseOverflow(value.ToString(), out bool clip))
            {
                if (!clip)
                {
                    //We actually perform the removal of the values from the style
                    //And then return false so no values are set.

                    style.RemoveValue(StyleKeys.ClipLeftKey);
                    style.RemoveValue(StyleKeys.ClipRightKey);
                    clipping = PDFUnit.Empty;
                    return(false);
                }
                else
                {
                    clipping = (PDFUnit)0.1;
                    return(true);
                }
            }
            else
            {
                clipping = PDFUnit.Empty;
                return(false);
            }
        }
        public void Text_FirstLineInsetTest()
        {
            TextStyle target   = new TextStyle();
            PDFUnit   expected = PDFUnit.Zero;

            Assert.AreEqual(expected, target.FirstLineInset);


            expected = 10;
            PDFUnit actual;

            target.FirstLineInset = expected;
            actual = target.FirstLineInset;
            Assert.AreEqual(expected, actual);


            expected = new PDFUnit(20, PageUnits.Millimeters);
            target.FirstLineInset = expected;
            actual = target.FirstLineInset;
            Assert.AreEqual(expected, actual);


            expected = PDFUnit.Zero;
            target.RemoveFirstLineInset();
            actual = target.FirstLineInset;
            Assert.AreEqual(expected, actual);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Moves the point by x and y dimensions
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        protected static PDFPoint Translate(PDFPoint pt, PDFUnit x, PDFUnit y)
        {
            pt.X += x;
            pt.Y += y;

            return(pt);
        }
        protected bool DoConvertBgPos(StyleBase forstyle, object value, out PDFUnit size)
        {
            if (null == value)
            {
                size = PDFUnit.Empty;
                return(false);
            }
            else if (value is PDFUnit unit)
            {
                size = unit;
                return(true);
            }
            else
            {
                var str = value.ToString();

                if (PDFUnit.TryParse(str, out size))
                {
                    return(true);
                }
                else
                {
                    size = PDFUnit.Zero;
                    return(false);
                }
            }
        }
Ejemplo n.º 12
0
        protected virtual void CreateBlockRegions(PDFLayoutBlock containerBlock, PDFPositionOptions position, PDFColumnOptions columnOptions)
        {
            PDFRect unused  = containerBlock.CurrentRegion.UnusedBounds;
            PDFUnit yoffset = containerBlock.CurrentRegion.Height;

            PDFRect total = new PDFRect(PDFUnit.Zero, yoffset, unused.Width, unused.Height);

            if (position.Width.HasValue)
            {
                total.Width = position.Width.Value;
            }
            //ADDED for min/max sizes. Include the margins as we are making this the available width.
            else if (position.MaximumWidth.HasValue)
            {
                total.Width = position.MaximumWidth.Value + position.Margins.Left + position.Margins.Right;
            }


            if (position.Height.HasValue)
            {
                total.Height = position.Height.Value;
            }
            //ADDED for min/max sizes. Include the margins as we are making this the available height.
            else if (position.MaximumHeight.HasValue)
            {
                total.Height = position.MaximumHeight.Value + position.Margins.Top + position.Margins.Bottom;
            }

            CurrentBlock.InitRegions(total, position, columnOptions, this.Context);
        }
Ejemplo n.º 13
0
 public MockSubParameter()
 {
     this.Size       = (PDFUnit)30;
     this.BoldTitle  = true;
     this.Title      = "Mock object title";
     this.Background = new PDFColor(1, 0, 0);
 }
Ejemplo n.º 14
0
        protected override bool DoSetStyleValue(Style onStyle, CSSStyleItemReader reader)
        {
            PDFUnit size   = PDFUnit.Zero;
            bool    result = true;

            if (reader.ReadNextValue())
            {
                var str = reader.CurrentTextValue;
                if (IsExpression(str))
                {
                    result = this.AttachExpressionBindingHandler(onStyle, StyleKeys.FontSizeKey, str, DoConvertFontSize);
                }
                else if (TryGetFontSize(str, out size))
                {
                    onStyle.SetValue(StyleKeys.FontSizeKey, size);
                    result = true;
                }
                else
                {
                    result = false;
                }
            }
            else
            {
                result = false;
            }

            return(result);
        }
        /// <summary>
        /// Overrides the base method to close the current list block, and set up a new block in the provided region.
        /// Updates the references in this engine.
        /// </summary>
        /// <param name="blockToClose"></param>
        /// <param name="joinToRegion"></param>
        /// <returns></returns>
        public override PDFLayoutBlock CloseCurrentBlockAndStartNewInRegion(PDFLayoutBlock blockToClose, PDFLayoutRegion joinToRegion)
        {
            PDFLayoutBlock orig  = this.CurrentBlock;
            PDFRect        avail = this._listBlock.AvailableBounds;

            avail.Height = joinToRegion.AvailableHeight;
            PDFThickness margins = _listBlock.Position.Margins;

            PDFLayoutBlock newList = base.CloseCurrentBlockAndStartNewInRegion(blockToClose, joinToRegion);

            this.CurrentBlock = (PDFLayoutBlock)newList.Parent;

            this._listBlock = newList;
            avail.Y         = 0;

            avail.Width  -= margins.Left + margins.Right;
            avail.Height -= margins.Top + margins.Bottom;
            avail.X      += margins.Left;
            avail.Y      += margins.Top;

            this._listBlock.AvailableBounds = avail;
            this._itemoffset = 0;

            return(newList);
        }
        public void Text_WordSpacingTest()
        {
            TextStyle target = new TextStyle();

            // Default value

            PDFUnit expected = 0;
            PDFUnit actual   = target.WordSpacing;

            Assert.AreEqual(expected, actual);

            // Set Value

            expected           = 20;
            target.WordSpacing = expected;
            actual             = target.WordSpacing;
            Assert.AreEqual(expected, actual);

            // Change Value

            expected           = 10;
            target.WordSpacing = expected;
            actual             = target.WordSpacing;
            Assert.AreEqual(expected, actual);

            // Remove Value

            expected = 0;
            target.RemoveWordSpacing();
            actual = target.WordSpacing;
            Assert.AreEqual(expected, actual);
        }
        protected override bool DoConvertUnit(StyleBase onStyle, object value, out PDFUnit result)
        {
            bool success = false;

            if (null == value)
            {
                result = PDFUnit.Empty;
                return(false);
            }
            var str = value.ToString();

            if (string.Equals("thin", str, StringComparison.OrdinalIgnoreCase))
            {
                result  = ThinSize;
                success = true;
            }
            else if (string.Equals("medium", str, StringComparison.OrdinalIgnoreCase))
            {
                result  = MediumSize;
                success = true;
            }
            else if (string.Equals("thick", str, StringComparison.OrdinalIgnoreCase))
            {
                result  = ThickSize;
                success = true;
            }
            else
            {
                success = base.DoConvertUnit(onStyle, value, out result);
            }

            return(success);
        }
Ejemplo n.º 18
0
        public void CompareTo_Test()
        {
            PDFUnit width  = new PDFUnit(10, PageUnits.Millimeters);
            PDFUnit height = new PDFUnit(20, PageUnits.Inches);
            PDFSize target = new PDFSize(width, height);
            PDFSize other  = new PDFSize(width, height);

            int expected = 0;
            int actual;

            actual = target.CompareTo(other);
            Assert.AreEqual(expected, actual);

            height   = new PDFUnit(10, PageUnits.Inches);
            target   = new PDFSize(width, height);
            expected = -1;
            actual   = target.CompareTo(other);
            Assert.AreEqual(expected, actual);

            height   = new PDFUnit(40, PageUnits.Inches);
            target   = new PDFSize(width, height);
            expected = 1;
            actual   = target.CompareTo(other);
            Assert.AreEqual(expected, actual);
        }
Ejemplo n.º 19
0
        //
        // overrides
        //

        #region protected override bool DoClose(ref string msg)

        /// <summary>
        /// Overrides the default implementation to resize this region to either
        /// the explicit values or calculated values
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        protected override bool DoClose(ref string msg)
        {
            //We override this to reduce the size of the region so that it
            //fits the explicit size or the content within it

            PDFUnit h = PDFUnit.Zero;
            PDFUnit w = PDFUnit.Zero;

            //In theory there should just be one block
            foreach (PDFLayoutItem item in this.Contents)
            {
                h += item.Height;
                w  = PDFUnit.Max(w, item.Width);
            }

            if (this.PositionMode != Drawing.PositionMode.Absolute && this.PositionMode != Drawing.PositionMode.Relative)
            {
                if (this.PositionOptions.Width.HasValue)
                {
                    w = this.PositionOptions.Width.Value;
                }
                if (this.PositionOptions.Height.HasValue)
                {
                    h = this.PositionOptions.Height.Value;
                }
            }
            this.UsedSize    = new PDFSize(w, h);
            this.TotalBounds = new PDFRect(this.TotalBounds.Location, this.UsedSize);

            return(base.DoClose(ref msg));
        }
Ejemplo n.º 20
0
        public void op_Inequality_Test()
        {
            PDFUnit width  = new PDFUnit(10, PageUnits.Millimeters);
            PDFUnit height = new PDFUnit(20, PageUnits.Inches);
            PDFSize target = new PDFSize(width, height);
            PDFSize other  = new PDFSize(width, height);

            bool expected = false;
            bool actual;

            actual = (target != other);
            Assert.AreEqual(expected, actual);

            height   = new PDFUnit(40, PageUnits.Inches);
            other    = new PDFSize(width, height);
            expected = true;
            actual   = (target != other);
            Assert.AreEqual(expected, actual);

            width    = new PDFUnit(20, PageUnits.Millimeters);
            height   = new PDFUnit(20, PageUnits.Inches);
            other    = new PDFSize(width, height);
            expected = true;
            actual   = (target != other);
            Assert.AreEqual(expected, actual);
        }
Ejemplo n.º 21
0
        public void Size_WidthTest()
        {
            SizeStyle target = new SizeStyle();

            // Default value

            PDFUnit expected = PDFUnit.Empty;
            PDFUnit actual   = target.Width;

            Assert.AreEqual(expected, actual);

            // Set Value

            expected     = 20;
            target.Width = expected;
            actual       = target.Width;
            Assert.AreEqual(expected, actual);

            // Change Value

            expected     = new PDFUnit(120, PageUnits.Millimeters);
            target.Width = expected;
            actual       = target.Width;
            Assert.AreEqual(expected, actual);

            // Remove Value

            expected = PDFUnit.Empty;
            target.RemoveWidth();
            actual = target.Width;
            Assert.AreEqual(expected, actual);
        }
        /// <summary>
        /// Moves the entire list block to a new region or page in the layout
        /// </summary>
        /// <param name="requiredHeight"></param>
        /// <returns></returns>
        protected virtual bool MoveFullListToNextRegion(PDFUnit requiredHeight)
        {
            if (_didmovefulllist)
            {
                this.Context.TraceLog.Add(TraceLevel.Error, ListEngineLogCategory, "Already moved list to the next region so cannot move list '" + this.List.ID + "' to the next region");
                return(false);
            }


            PDFLayoutBlock  block  = this._listBlock;
            PDFLayoutRegion region = this._listBlock.CurrentRegion;
            bool            newPage;

            if (this.MoveToNextRegion(requiredHeight, ref region, ref block, out newPage))
            {
                if (this.Context.ShouldLogVerbose)
                {
                    this.Context.TraceLog.Add(TraceLevel.Verbose, ListEngineLogCategory, "Moved entire list '" + this.List.ID + "' to the next " + (newPage ? "Page" : "Region") + " and list block is now '" + block.ToString() + "'");
                }

                //If we have a new block then we set the old one as invisible
                if (block != _listBlock)
                {
                    _listBlock.Position.Visibility = Visibility.None;
                }

                _listBlock       = block;
                _didmovefulllist = true;
                return(true);
            }
            else
            {
                return(false);
            }
        }
Ejemplo n.º 23
0
 /// <summary>
 /// Overides the base (empty) implementation so that the FullWidth is set correctly
 /// </summary>
 /// <param name="width"></param>
 public override void SetMaxWidth(PDFUnit width)
 {
     if (this.FullWidth > width)
     {
         this.FullWidth = width;
     }
 }
Ejemplo n.º 24
0
        /// <summary>
        /// Tries to parse a CSS Unit value (e.g. 20px, 40cm) into a PDFUnit value, returning true if successful
        /// </summary>
        /// <param name="part"></param>
        /// <param name="unit"></param>
        /// <returns></returns>
        public static bool ParseCSSUnit(string part, out PDFUnit unit)
        {
            double factor;
            double parsed;
            int    unitLength;

            if (EndsWithRelativeUnit(part))
            {
                unit = PDFUnit.Zero;
                return(false);
            }
            else if (EndsWithAbsoluteUnit(part, out unitLength, out factor))
            {
                if (unitLength > 0)
                {
                    if (double.TryParse(part.Substring(0, part.Length - unitLength), out parsed))
                    {
                        unit = new PDFUnit(parsed * factor, PageUnits.Points);
                        return(true);
                    }
                }
            }
            else if (double.TryParse(part, out parsed))
            {
                unit = new PDFUnit(parsed, PageUnits.Points);
                return(true);
            }

            // could not parse
            unit = PDFUnit.Zero;
            return(false);
        }
        /// <summary>
        /// Adds a spacer of the required width (and height) to the line - inheritors can override this value
        /// </summary>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <param name="line"></param>
        protected virtual PDFTextRunSpacer AddLineInsetRun(PDFUnit w, PDFUnit h, PDFLayoutLine line)
        {
            PDFTextRunSpacer spacer = new PDFTextRunSpacer(w, h, line, this.TextComponent);

            line.AddRun(spacer);
            return(spacer);
        }
Ejemplo n.º 26
0
        //
        // implementation
        //

        public override void SetOffsetY(PDFUnit y)
        {
            base.SetOffsetY(y);
            PDFRect bounds = this.TotalBounds;

            bounds.Y        += y;
            this.TotalBounds = bounds;
        }
        /// <summary>
        /// We need to start the text
        /// </summary>
        protected virtual bool StartText()
        {
            if (this.Context.ShouldLogDebug)
            {
                this.Context.TraceLog.Begin(TraceLevel.Verbose, LOG_CATEGORY, "Starting the layout of text component " + this.TextComponent.ID);
            }
            bool          started;
            PDFLayoutLine line = this.EnsureFirstLineAvailable(out started);

            if (null == line)
            {
                this.ContinueLayout = false;
                return(false);
            }

            this.CurrentLine = line;

            this.Context.Graphics.SetCurrentFont(this.TextRenderOptions.Font);

            PDFUnit inset = PDFUnit.Zero;

            if (line.IsEmpty == false)
            {
                inset = line.Width;
            }
            else if (this.TextRenderOptions.FirstLineInset.HasValue && (this.Position.PositionMode != PositionMode.Inline || started))
            {
                inset = this.TextRenderOptions.FirstLineInset.Value;
                if (inset > 0)
                {
                    PDFTextRunSpacer spacer = new PDFTextRunSpacer(inset, 1, line, null);
                    line.AddRun(spacer);
                }
            }


            PDFTextRunBegin begin = new PDFTextRunBegin(this.TextRenderOptions, this.CurrentLine, this.TextComponent);

            begin.LineInset = inset;

            this.CurrentLine.AddRun(begin);
            begin.SetOffsetY(this.CurrentLine.OffsetY);


            this.CurrentLineInset = inset;
            this.BeginningRun     = begin;

            if (this.Context.ShouldLogDebug)
            {
                this.Context.TraceLog.End(TraceLevel.Verbose, LOG_CATEGORY, "Completed the layout of text component " + this.TextComponent.ID);
            }
            else if (this.Context.ShouldLogVerbose)
            {
                this.Context.TraceLog.Add(TraceLevel.Verbose, LOG_CATEGORY, "Laid out text component " + this.TextComponent.ID);
            }

            return(true);
        }
Ejemplo n.º 28
0
        public void PDFPointConstructor_Test()
        {
            PDFUnit  x      = new PDFUnit(10, PageUnits.Millimeters);
            PDFUnit  y      = new PDFUnit(20, PageUnits.Millimeters);
            PDFPoint target = new PDFPoint(x, y);

            Assert.AreEqual(x, target.X);
            Assert.AreEqual(y, target.Y);
        }
Ejemplo n.º 29
0
        //
        // ctor(s)
        //

        #region public PDFLayoutLine(PDFLayoutRegion region, PDFUnit fullwidth)

        /// <summary>
        /// Creates a new line in the specified region.
        /// </summary>
        /// <param name="region">The region that contains this line</param>
        /// <param name="fullwidth">The full available horizontal space for this line </param>
        public PDFLayoutLine(PDFLayoutRegion region, PDFUnit fullwidth, HorizontalAlignment halign, VerticalAlignment valign, int lineindex)
            : base(region, null)
        {
            this.FullWidth      = fullwidth;
            this.HAlignment     = halign;
            this.VAlignment     = valign;
            this.LineIndex      = lineindex;
            this.BaseLineOffset = 0;
        }
        protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset)
        {
            if (xoffset > 0)
            {
                this._w += xoffset;
            }

            base.DoPushComponentLayout(context, pageIndex, xoffset, yoffset);
        }