/** * <param name="widgetName">Widget name. It corresponds to the on-state name.</param> */ public DualWidget( Page page, RectangleF box, string widgetName ) : base(page, box) { // Initialize the on-state appearance! /* * NOTE: This is necessary to keep the reference to the on-state name. */ Appearance appearance = new Appearance(page.Document); Appearance = appearance; AppearanceStates normalAppearance = appearance.Normal; normalAppearance[new PdfName(widgetName)] = new FormXObject(page.Document, box.Size); }
/* * TODO: refresh should happen just before serialization, on document event (e.g. OnWrite()) */ private void RefreshAppearance( ) { FormXObject normalAppearance; RectangleF box = org.pdfclown.objects.Rectangle.Wrap(BaseDataObject[PdfName.Rect]).ToRectangleF(); { AppearanceStates normalAppearances = Appearance.Normal; normalAppearance = normalAppearances[null]; if (normalAppearance != null) { normalAppearance.Box = box; normalAppearance.BaseDataObject.Body.SetLength(0); } else { normalAppearances[null] = normalAppearance = new FormXObject(Document, box); } } PrimitiveComposer composer = new PrimitiveComposer(normalAppearance); { float yOffset = box.Height - Page.Box.Height; MarkupTypeEnum markupType = MarkupType; switch (markupType) { case MarkupTypeEnum.Highlight: { ExtGState defaultExtGState; { ExtGStateResources extGStates = normalAppearance.Resources.ExtGStates; defaultExtGState = extGStates[HighlightExtGStateName]; if (defaultExtGState == null) { if (extGStates.Count > 0) { extGStates.Clear(); } extGStates[HighlightExtGStateName] = defaultExtGState = new ExtGState(Document); defaultExtGState.AlphaShape = false; defaultExtGState.BlendMode = new List <BlendModeEnum>(new BlendModeEnum[] { BlendModeEnum.Multiply }); } } composer.ApplyState(defaultExtGState); composer.SetFillColor(Color); { foreach (Quad markupBox in MarkupBoxes) { PointF[] points = markupBox.Points; float markupBoxHeight = points[3].Y - points[0].Y; float markupBoxMargin = GetMarkupBoxMargin(markupBoxHeight); composer.DrawCurve( new PointF(points[3].X, points[3].Y + yOffset), new PointF(points[0].X, points[0].Y + yOffset), new PointF(points[3].X - markupBoxMargin, points[3].Y - markupBoxMargin + yOffset), new PointF(points[0].X - markupBoxMargin, points[0].Y + markupBoxMargin + yOffset) ); composer.DrawLine( new PointF(points[1].X, points[1].Y + yOffset) ); composer.DrawCurve( new PointF(points[2].X, points[2].Y + yOffset), new PointF(points[1].X + markupBoxMargin, points[1].Y + markupBoxMargin + yOffset), new PointF(points[2].X + markupBoxMargin, points[2].Y - markupBoxMargin + yOffset) ); composer.Fill(); } } } break; case MarkupTypeEnum.Squiggly: { composer.SetStrokeColor(Color); composer.SetLineCap(LineCapEnum.Round); composer.SetLineJoin(LineJoinEnum.Round); { foreach (Quad markupBox in MarkupBoxes) { PointF[] points = markupBox.Points; float markupBoxHeight = points[3].Y - points[0].Y; float lineWidth = markupBoxHeight * .05f; float step = markupBoxHeight * .125f; float boxXOffset = points[3].X; float boxYOffset = points[3].Y + yOffset - lineWidth; bool phase = false; composer.SetLineWidth(lineWidth); for (float x = 0, xEnd = points[2].X - boxXOffset; x < xEnd || !phase; x += step) { PointF point = new PointF(x + boxXOffset, (phase ? -step : 0) + boxYOffset); if (x == 0) { composer.StartPath(point); } else { composer.DrawLine(point); } phase = !phase; } } composer.Stroke(); } } break; case MarkupTypeEnum.StrikeOut: case MarkupTypeEnum.Underline: { composer.SetStrokeColor(Color); { float lineYRatio = 0; switch (markupType) { case MarkupTypeEnum.StrikeOut: lineYRatio = .5f; break; case MarkupTypeEnum.Underline: lineYRatio = .9f; break; default: throw new NotImplementedException(); } foreach (Quad markupBox in MarkupBoxes) { PointF[] points = markupBox.Points; float markupBoxHeight = points[3].Y - points[0].Y; float boxYOffset = markupBoxHeight * lineYRatio + yOffset; composer.SetLineWidth(markupBoxHeight * .065); composer.DrawLine( new PointF(points[3].X, points[0].Y + boxYOffset), new PointF(points[2].X, points[1].Y + boxYOffset) ); } composer.Stroke(); } } break; default: throw new NotImplementedException(); } } composer.Flush(); }