public void Draw(IGraphicsTarget grTarget, float x, float y, int startLine, int countLines) { if (startLine != 0 || countLines < boxes.Height) writer.WriteLine("@ ({1},{2}) partial description '{0}' [start:{3} count:{4}]", id, x, y, startLine, countLines, x, y); else writer.WriteLine("@ ({1},{2}) description '{0}'", id, x, y); }
// Render the punchcard onto the given graphics at (0,0). Only draw the parts that lie within // the clip rect. void Render(IGraphicsTarget g, int startLine, int countLines) { PointF upperLeft = new PointF(margin, margin); // upper left of the current line. List <CourseView.ControlView> boxes = GetAllBoxes(); // mapping from box number to control views. int lineCount = NumberOfLines(boxes); CreateObjects(g); try { for (int line = 0; line <= lineCount; ++line) { if (line >= startLine && line < startLine + countLines) { Matrix matrixNew; // Set transform so the each cell is 100x100, and the origin of the line is at (0,0). matrixNew = new Matrix(); matrixNew.Translate(upperLeft.X, upperLeft.Y); matrixNew.Scale(cellSize / 100.0F, cellSize / 100.0F); g.PushTransform(matrixNew); // Draw the line. RenderLine(g, boxes, line, (line == lineCount || line == startLine + countLines - 1)); g.PopTransform(); upperLeft.Y += cellSize; } } } finally { DisposeObjects(); } }
/// <summary> /// Draw the given symbol to fill the rectange in that graphics. /// </summary> /// <param name="g">Graphics to draw in.</param> /// <param name="color">Color to use for drawing.</param> /// <param name="rect">The rectange to fill.</param> public void Draw(IGraphicsTarget g, CmykColor color, RectangleF rect) { Matrix matNew = new Matrix(); matNew.Translate((rect.Left + rect.Right) / 2.0F, (rect.Top + rect.Bottom) / 2.0F); if (kind >= 'T') { // An instructional directive that spans 8 columns matNew.Scale(rect.Width / 1600.0F, -rect.Height / 200.0F); } else { // Regular square symbol. matNew.Scale(rect.Width / 200.0F, -rect.Height / 200.0F); } g.PushTransform(matNew); for (int i = 0; i < strokes.Length; ++i) { strokes[i].Draw(g, color); } g.PopTransform(); }
public void Draw(IGraphicsTarget grTarget, float x, float y, int startLine, int countLines) { Matrix transform = new Matrix(); transform.Translate(x, y); grTarget.PushTransform(transform); Render(grTarget, startLine, countLines); grTarget.PopTransform(); }
// Draws a given page. 0 is the first page. public void DrawPage(IGraphicsTarget grTarget, int pageNumber) { foreach (PositionedRectangle positionedRectangle in positions) { if (positionedRectangle.pageNumber == pageNumber) { positionedRectangle.description.Draw(grTarget, positionedRectangle.location.X, positionedRectangle.location.Y, positionedRectangle.startLine, positionedRectangle.countLines); } } }
private void PushRectangleClip(IGraphicsTarget graphicsTarget, RectangleF rect) { object rectanglePath = new object(); graphicsTarget.CreatePath(rectanglePath, new List <GraphicsPathPart> { new GraphicsPathPart(GraphicsPathPartKind.Start, new PointF[] { rect.Location }), new GraphicsPathPart(GraphicsPathPartKind.Lines, new PointF[] { new PointF(rect.Right, rect.Top), new PointF(rect.Right, rect.Bottom), new PointF(rect.Left, rect.Bottom), new PointF(rect.Left, rect.Top) }), new GraphicsPathPart(GraphicsPathPartKind.Close, new PointF[0]) }, FillMode.Winding); graphicsTarget.PushClip(rectanglePath); }
// Create pens and fonts we use. void CreateObjects(IGraphicsTarget g) { CmykColor black = CmykColor.FromCmyk(0, 0, 0, 1); blackBrush = new object(); g.CreateSolidBrush(blackBrush, black); thinPen = new object(); g.CreatePen(thinPen, black, PunchcardAppearance.thinLine, LineCap.Flat, LineJoin.Miter, 5F); thickPen = new object(); g.CreatePen(thickPen, black, PunchcardAppearance.thickLine, LineCap.Flat, LineJoin.Miter, 5F); textMetrics = new GDIPlus_TextMetrics(); }
public void Draw(IGraphicsTarget g, CmykColor color) { object brush = new object(); object pen = new object(); if (kind == SymbolStrokes.Circle || kind == SymbolStrokes.Polyline || kind == SymbolStrokes.Polygon || kind == SymbolStrokes.PolyBezier) { g.CreatePen(pen, color, thickness, ends, corners, 5); } else { g.CreateSolidBrush(brush, color); } switch (kind) { case SymbolStrokes.Disc: g.FillEllipse(brush, points[0], radius, radius); break; case SymbolStrokes.Circle: g.DrawEllipse(pen, points[0], radius, radius); break; case SymbolStrokes.Polyline: g.DrawPolyline(pen, points); break; case SymbolStrokes.Polygon: g.DrawPolygon(pen, points); break; case SymbolStrokes.FilledPolygon: g.FillPolygon(brush, points, FillMode.Alternate); break; case SymbolStrokes.PolyBezier: g.DrawPath(pen, CreateBezierPath(points)); break; case SymbolStrokes.FilledPolyBezier: g.FillPath(brush, CreateBezierPath(points)); break; default: Debug.Fail("Bad SymbolStroke kind"); break; } }
public void PrintToPdf(string pathName, bool cmykMode) { PdfWriter pdfWriter = new PdfWriter(Path.GetFileNameWithoutExtension(pathName), cmykMode); // Set up and position everything. printPreviewInProgress = false; printingToBitmaps = false; SetupPrinting(); PrintEventArgs printArgs = new PrintEventArgs(); BeginPrint(this, printArgs); while (currentPage < totalPages) { // Set the page settings. QueryPageSettingsEventArgs queryPageSettingsArgs = new QueryPageSettingsEventArgs(pageSettings); QueryPageSettings(this, queryPageSettingsArgs); Size pageSize = pageSettings.Bounds.Size; SizeF paperSizeInInches = new SizeF(pageSize.Width / 100F, pageSize.Height / 100F); Rectangle pageBounds = pageSettings.Bounds; Rectangle marginBounds = Rectangle.FromLTRB(pageBounds.Left + pageSettings.Margins.Left, pageBounds.Top + pageSettings.Margins.Top, pageBounds.Right - pageSettings.Margins.Right, pageBounds.Bottom - pageSettings.Margins.Bottom); float dpi = 1200; // Make a PDF high resolution, although this is unlikely to matter much. // create and print a page. using (IGraphicsTarget grTarget = pdfWriter.BeginPage(paperSizeInInches)) { // Move the origin of the graphics to the margin boundaries. Matrix translateTransform = new Matrix(); translateTransform.Translate(marginBounds.Left, marginBounds.Top); grTarget.PushTransform(translateTransform); SizeF size = new SizeF(marginBounds.Width, marginBounds.Height); DrawPage(grTarget, currentPage, size, dpi); grTarget.PopTransform(); } ++currentPage; } EndPrint(this, printArgs); pdfWriter.Save(pathName); }
// Draw a pattern of dots. The center of the edge dots are on the edges of the given rectangle, so the dots // protrude out a dot radius from the rectangle. private void DrawPattern(IGraphicsTarget g, PunchPattern pattern, RectangleF punchRect) { float dxPerDot = (pattern.size > 1) ? punchRect.Width / (pattern.size - 1) : 0; float dyPerDot = (pattern.size > 1) ? punchRect.Height / (pattern.size - 1) : 0; float r = PunchcardAppearance.dotRadius; for (int row = 0; row < pattern.size; ++row) { for (int col = 0; col < pattern.size; ++col) { if (pattern.dots[row, col]) { float xCenter = punchRect.Left + dxPerDot * col; float yCenter = punchRect.Top + dyPerDot * row; g.FillEllipse(blackBrush, new PointF(xCenter, yCenter), r, r); } } } }
// The core printing routine. void DrawPage(IGraphicsTarget graphicsTarget, CoursePage page) { // Get the course view for the course we are printing. CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator); // Get the correct purple color to print the course in. short ocadId; float purpleC, purpleM, purpleY, purpleK; bool purpleOverprint; FindPurple.GetPurpleColor(mapDisplay, appearance, out ocadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint); // Create a course layout from the view. CourseLayout layout = new CourseLayout(); layout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false); layout.SetLayerColor(CourseLayer.MainCourse, ocadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, purpleOverprint); CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, CourseLayer.MainCourse); // Set the course layout into the map display mapDisplay.SetCourse(layout); mapDisplay.SetPrintArea(null); // Set the transform, and the clip. Matrix transform = Geometry.CreateInvertedRectangleTransform(page.mapRectangle, page.printRectangle); PushRectangleClip(graphicsTarget, page.printRectangle); graphicsTarget.PushTransform(transform); // Determine the resolution in map coordinates. Matrix inverseTransform = transform.Clone(); inverseTransform.Invert(); float minResolutionPage = 100F / 2400F; // Assume 2400 DPI as the base resolution, to get very accurate print. float minResolutionMap = Geometry.TransformDistance(minResolutionPage, inverseTransform); // And draw. mapDisplay.Draw(graphicsTarget, page.mapRectangle, minResolutionMap); graphicsTarget.PopTransform(); graphicsTarget.PopClip(); }
// Draw the bitmap map part. void DrawBitmapMap(IGraphicsTarget grTarget, RectangleF visRect, float minResolution) { // Setup transform. grTarget.PushTransform(BitmapTransform()); // Setup drawing map and intensity. BitmapScaling scalingMode = antialiased ? BitmapScaling.MediumQuality : BitmapScaling.NearestNeighbor; if (bitmap.PixelHeight * bitmap.PixelWidth > 50000000) { scalingMode = BitmapScaling.NearestNeighbor; // Turn off high quality scaling for very large bitmaps. } // Get source bitmap. Use the dimmed bitmap if there is one. IGraphicsBitmap sourceBitmap; if (dimmedBitmap != null) { sourceBitmap = dimmedBitmap; } else { sourceBitmap = bitmap; } // Draw it. grTarget.DrawBitmap(sourceBitmap, new RectangleF(0, 0, bitmap.PixelWidth, bitmap.PixelHeight), scalingMode, minResolution); if (mapIntensity < 0.99 && sourceBitmap == bitmap) { // Dimming desired, but we don't have a dimmed bitmap. Use an alpha mask instead. CmykColor dimmedWhite = CmykColor.FromCmyka(0, 0, 0, 0, 1 - mapIntensity); object brush = new object(); grTarget.CreateSolidBrush(brush, dimmedWhite); grTarget.FillRectangle(brush, new RectangleF(0, 0, bitmap.PixelWidth, bitmap.PixelHeight)); } // Pop transform grTarget.PopTransform(); }
// Render one punch box private void RenderPunchBox(IGraphicsTarget g, CourseView.ControlView controlView, RectangleF rect) { // Draw the ordinal number, if there is one. if (controlView.ordinal > 0) { DrawSingleLineText(g, controlView.ordinal.ToString(), PunchcardAppearance.controlNumberFont, new PointF(rect.Left + 6, rect.Top + 3), StringAlignment.Near, StringAlignment.Near); } // If it's a score course, and a score has been defined, then put the score. if (courseView.Kind == CourseView.CourseViewKind.Score) { int points = 0; if (controlView.courseControlIds[0].IsNotNone) { points = eventDB.GetCourseControl(controlView.courseControlIds[0]).points; } if (points > 0) { DrawSingleLineText(g, points.ToString(), PunchcardAppearance.scoreFont, new PointF((rect.Left + rect.Right) / 2, rect.Top + 3), StringAlignment.Center, StringAlignment.Near); } } // Draw the code. string code = string.Format("({0})", eventDB.GetControl(controlView.controlId).code); DrawSingleLineText(g, code, PunchcardAppearance.codeFont, new PointF(rect.Right - 5F, rect.Top + 3), StringAlignment.Far, StringAlignment.Near); // Draw the punch pattern. RectangleF punchRect = RectangleF.FromLTRB(rect.Left + 20F, rect.Top + 27.5F, rect.Right - 20F, rect.Bottom - 12.5F); PunchPattern pattern = eventDB.GetControl(controlView.controlId).punches; if (pattern != null) { DrawPattern(g, pattern, punchRect); } }
private void DrawSingleLineText(IGraphicsTarget g, string text, FontDesc fontDesc, PointF pt, StringAlignment horizAlignment, StringAlignment vertAlignment) { object font = new object(); g.CreateFont(font, fontDesc.Name, fontDesc.EmHeight, fontDesc.TextEffects); ITextFaceMetrics fontMetrics = textMetrics.GetTextFaceMetrics(fontDesc.Name, fontDesc.EmHeight, fontDesc.TextEffects); SizeF size = fontMetrics.GetTextSize(text); switch (horizAlignment) { case StringAlignment.Near: break; case StringAlignment.Center: pt.X = pt.X - size.Width / 2F; break; case StringAlignment.Far: pt.X = pt.X - size.Width; break; } switch (vertAlignment) { case StringAlignment.Near: break; case StringAlignment.Center: pt.Y = pt.Y - size.Height / 2F; break; case StringAlignment.Far: pt.Y = pt.Y - size.Height; break; } g.DrawText(text, font, blackBrush, pt); fontMetrics.Dispose(); }
// The core printing routine. The origin of the graphics is the upper-left of the margins, // and the printArea in the size to draw into (in hundreths of an inch). protected override void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi) { CoursePage page = pages[pageNumber]; // Get the course view for the course we are printing. CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator); // Get the correct purple color to print the course in. short ocadId; float purpleC, purpleM, purpleY, purpleK; bool purpleOverprint; FindPurple.GetPurpleColor(mapDisplay, appearance, out ocadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint); // Create a course layout from the view. CourseLayout layout = new CourseLayout(); layout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false); layout.SetLayerColor(CourseLayer.MainCourse, ocadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, purpleOverprint); CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, CourseLayer.MainCourse); // Set the course layout into the map display mapDisplay.SetCourse(layout); this.mapDisplay.SetPrintArea(null); // Collecting garbage should make out of memory less common. GC.Collect(); if (graphicsTarget is GDIPlus_GraphicsTarget) { // We print to intermediate bands of bitmaps. This is the only way to get purple blending correct. // Other code ensure that if purple blending is on, we always take this code path. GDIPlus_GraphicsTarget gdiGraphicsTarget = ((GDIPlus_GraphicsTarget)graphicsTarget); Graphics g = gdiGraphicsTarget.Graphics; // Save and restore state so we can mess with stuff. GraphicsState graphicsState = g.Save(); // Printing via a bitmap. Works best with some print drivers. dpi = AdjustDpi(dpi); const long MAX_PIXELS_PER_BAND = 20000000; // 20M pixels = 60M bytes (3 bytes per pixel). List <CoursePage> bands = BandPageToLimitBitmapSize(page, dpi, MAX_PIXELS_PER_BAND); // Create the bitmap. Can do this once because each band is the same size. int bitmapWidth = (int)Math.Round(bands[0].printRectangle.Width * dpi / 100F); int bitmapHeight = (int)Math.Round(bands[0].printRectangle.Height * dpi / 100F); Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb); foreach (CoursePage band in bands) { // Set the transform Matrix transform = Geometry.CreateInvertedRectangleTransform(band.mapRectangle, new RectangleF(0, 0, bitmapWidth, bitmapHeight)); mapDisplay.Draw(bitmap, transform); try { // Draw the bitmap on the printer. g.DrawImage(bitmap, band.printRectangle); } catch (Exception) { } } // restore state. g.Restore(graphicsState); bitmap.Dispose(); } else { // Print directly. Used only when prerasterization is off. // Set the transform, and the clip. Matrix transform = Geometry.CreateInvertedRectangleTransform(page.mapRectangle, page.printRectangle); PushRectangleClip(graphicsTarget, page.printRectangle); graphicsTarget.PushTransform(transform); // Determine the resolution in map coordinates. Matrix inverseTransform = transform.Clone(); inverseTransform.Invert(); float minResolutionPage = 100F / dpi; float minResolutionMap = Geometry.TransformDistance(minResolutionPage, inverseTransform); // And draw. mapDisplay.Draw(graphicsTarget, page.mapRectangle, minResolutionMap); graphicsTarget.PopTransform(); graphicsTarget.PopClip(); } }
// Draw the map and course onto a graphics. A helper for the other two draw methods. private void DrawHelper(IGraphicsTarget grTargetOcadMap, IGraphicsTarget grTargetBitmapMap, IGraphicsTarget grTargetCourses, RectangleF visRect, float minResolution) { RenderOptions renderOptions = new RenderOptions(); renderOptions.minResolution = minResolution; if (Printing) { renderOptions.usePatternBitmaps = false; // don't use pattern bitmaps when printing, they cause some problems in some printer drivers and we want best quality. } else if (antialiased && minResolution < 0.007F) // use pattern bitmaps unless high quality and zoomed in very far { renderOptions.usePatternBitmaps = false; } else { renderOptions.usePatternBitmaps = true; } renderOptions.showSymbolBounds = showBounds; renderOptions.renderTemplates = RenderTemplateOption.MapAndTemplates; renderOptions.blendOverprintedColors = ocadOverprintEffect; // First draw the real map. switch (mapType) { case MapType.OCAD: grTargetOcadMap.PushAntiAliasing(Printing ? false : antialiased); // don't anti-alias on printer DrawOcadMap(grTargetOcadMap, visRect, renderOptions); grTargetOcadMap.PopAntiAliasing(); break; case MapType.Bitmap: case MapType.PDF: grTargetBitmapMap.PushAntiAliasing(Printing ? false : antialiased); // don't anti-alias on printer DrawBitmapMap(grTargetBitmapMap, visRect, minResolution); grTargetBitmapMap.PopAntiAliasing(); break; case MapType.None: break; } // Now draw the courseMap on top. if (Printing) { grTargetCourses.PushAntiAliasing(false); } else { grTargetCourses.PushAntiAliasing(true); // always anti-alias the course unless printing } // Always turn blending on. renderOptions.blendOverprintedColors = true; if (courseMap != null) { using (courseMap.Read()) courseMap.Draw(grTargetCourses, visRect, renderOptions, null); } grTargetCourses.PopAntiAliasing(); grTargetCourses.PushAntiAliasing(false); if (printArea.HasValue && !printArea.Value.Contains(visRect)) { object printAreaOutline = new object(); grTargetCourses.CreateSolidBrush(printAreaOutline, CmykColor.FromCmyka(0, 0, 0, 1, 0.12F)); if (printArea.Value.Top > visRect.Top) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, visRect.Top, visRect.Right, printArea.Value.Top); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Bottom < visRect.Bottom) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, printArea.Value.Bottom, visRect.Right, visRect.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Left > visRect.Left) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, printArea.Value.Top, printArea.Value.Left, printArea.Value.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Right < visRect.Right) { RectangleF draw = RectangleF.FromLTRB(printArea.Value.Right, printArea.Value.Top, visRect.Right, printArea.Value.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } } grTargetCourses.PopAntiAliasing(); }
// The core printing routine. The origin of the graphics is the upper-left of the margins, // and the printArea in the size to draw into (in hundreths of an inch). protected override void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi) { Graphics g = ((GDIPlus_GraphicsTarget)graphicsTarget).Graphics; positioner.DrawPage(g, pageNumber); }
// Draw the map and course onto a graphics target. The color model is ignored. The intensity // must be 1, and purple blending is never performed. public void Draw(IGraphicsTarget grTarget, RectangleF visRect, float minResolution) { Debug.Assert(MapIntensity == 1.0F); DrawHelper(grTarget, grTarget, grTarget, visRect, minResolution); }
// The core printing routine. The origin of the graphics is the upper-left of the margins, // and the printArea in the size to draw into (in hundreths of an inch). protected override void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi) { CoursePage page = pages[pageNumber]; // Get the course view for the course we are printing. CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator); // Get the correct purple color to print the course in. short ocadId; float purpleC, purpleM, purpleY, purpleK; bool purpleOverprint; FindPurple.GetPurpleColor(mapDisplay, appearance, out ocadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint); // Create a course layout from the view. CourseLayout layout = new CourseLayout(); layout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false); layout.SetLayerColor(CourseLayer.MainCourse, ocadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, purpleOverprint); CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, CourseLayer.MainCourse); // Set the course layout into the map display mapDisplay.SetCourse(layout); this.mapDisplay.SetPrintArea(null); // Collecting garbage should make out of memory less common. GC.Collect(); if (graphicsTarget is GDIPlus_GraphicsTarget) { // We print to intermediate bands of bitmaps. This is the only way to get purple blending correct. // Other code ensure that if purple blending is on, we always take this code path. GDIPlus_GraphicsTarget gdiGraphicsTarget = ((GDIPlus_GraphicsTarget)graphicsTarget); Graphics g = gdiGraphicsTarget.Graphics; // Save and restore state so we can mess with stuff. GraphicsState graphicsState = g.Save(); // Printing via a bitmap. Works best with some print drivers. dpi = AdjustDpi(dpi); const long MAX_PIXELS_PER_BAND = 20000000; // 20M pixels = 60M bytes (3 bytes per pixel). List<CoursePage> bands = BandPageToLimitBitmapSize(page, dpi, MAX_PIXELS_PER_BAND); // Create the bitmap. Can do this once because each band is the same size. int bitmapWidth = (int) Math.Round(bands[0].printRectangle.Width * dpi / 100F); int bitmapHeight = (int) Math.Round(bands[0].printRectangle.Height * dpi / 100F); Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb); foreach (CoursePage band in bands) { // Set the transform Matrix transform = Geometry.CreateInvertedRectangleTransform(band.mapRectangle, new RectangleF(0, 0, bitmapWidth, bitmapHeight)); mapDisplay.Draw(bitmap, transform); // Draw the bitmap on the printer. g.DrawImage(bitmap, band.printRectangle); } // restore state. g.Restore(graphicsState); bitmap.Dispose(); } else { // Print directly. Used only when prerasterization is off. // Set the transform, and the clip. Matrix transform = Geometry.CreateInvertedRectangleTransform(page.mapRectangle, page.printRectangle); PushRectangleClip(graphicsTarget, page.printRectangle); graphicsTarget.PushTransform(transform); // Determine the resolution in map coordinates. Matrix inverseTransform = transform.Clone(); inverseTransform.Invert(); float minResolutionPage = 100F / dpi; float minResolutionMap = Geometry.TransformDistance(minResolutionPage, inverseTransform); // And draw. mapDisplay.Draw(graphicsTarget, page.mapRectangle, minResolutionMap); graphicsTarget.PopTransform(); graphicsTarget.PopClip(); } }
// The core printing routine. The origin of the graphics is the upper-left of the margins, // and the printArea is the size to draw into (in hundreths of an inch), within the margins. // dpi is the resolution of the printing in dots per inch. protected abstract void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi);
// Draw the map and course onto a graphics. A helper for the other two draw methods. private void DrawHelper(IGraphicsTarget grTargetOcadMap, IGraphicsTarget grTargetBitmapMap, IGraphicsTarget grTargetCourses, RectangleF visRect, float minResolution) { RenderOptions renderOptions = new RenderOptions(); renderOptions.minResolution = minResolution; if (Printing) renderOptions.usePatternBitmaps = false; // don't use pattern bitmaps when printing, they cause some problems in some printer drivers and we want best quality. else if (antialiased && minResolution < 0.007F) // use pattern bitmaps unless high quality and zoomed in very far renderOptions.usePatternBitmaps = false; else renderOptions.usePatternBitmaps = true; renderOptions.showSymbolBounds = showBounds; renderOptions.renderTemplates = RenderTemplateOption.MapAndTemplates; renderOptions.blendOverprintedColors = ocadOverprintEffect; // First draw the real map. switch (mapType) { case MapType.OCAD: grTargetOcadMap.PushAntiAliasing(Printing ? false : antialiased); // don't anti-alias on printer DrawOcadMap(grTargetOcadMap, visRect, renderOptions); grTargetOcadMap.PopAntiAliasing(); break; case MapType.Bitmap: case MapType.PDF: grTargetBitmapMap.PushAntiAliasing(Printing ? false : antialiased); // don't anti-alias on printer DrawBitmapMap(grTargetBitmapMap, visRect, minResolution); grTargetBitmapMap.PopAntiAliasing(); break; case MapType.None: break; } // Now draw the courseMap on top. if (Printing) grTargetCourses.PushAntiAliasing(false); else grTargetCourses.PushAntiAliasing(true); // always anti-alias the course unless printing // Always turn blending on. renderOptions.blendOverprintedColors = true; if (courseMap != null) { using (courseMap.Read()) courseMap.Draw(grTargetCourses, visRect, renderOptions, null); } grTargetCourses.PopAntiAliasing(); grTargetCourses.PushAntiAliasing(false); if (printArea.HasValue && !printArea.Value.Contains(visRect)) { object printAreaOutline = new object(); grTargetCourses.CreateSolidBrush(printAreaOutline, CmykColor.FromCmyka(0, 0, 0, 1, 0.12F)); if (printArea.Value.Top > visRect.Top) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, visRect.Top, visRect.Right, printArea.Value.Top); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Bottom < visRect.Bottom) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, printArea.Value.Bottom, visRect.Right, visRect.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Left > visRect.Left) { RectangleF draw = RectangleF.FromLTRB(visRect.Left, printArea.Value.Top, printArea.Value.Left, printArea.Value.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } if (printArea.Value.Right < visRect.Right) { RectangleF draw = RectangleF.FromLTRB(printArea.Value.Right, printArea.Value.Top, visRect.Right, printArea.Value.Bottom); grTargetCourses.FillRectangle(printAreaOutline, draw); } } grTargetCourses.PopAntiAliasing(); }
// Render a single line of the punchcard. "lastLine" is true if this is the last line (draws the bottom line). private void RenderLine(IGraphicsTarget g, List <CourseView.ControlView> boxes, int line, bool lastLine) { int lineCount = NumberOfLines(boxes); // Draw top line. float fullWidth = punchcardFormat.boxesAcross * 100; if (line == 0 || line == 1) { g.DrawLine(thickPen, new PointF(0, 0), new PointF(fullWidth, 0)); } else { g.DrawLine(thinPen, new PointF(0, 0), new PointF(fullWidth, 0)); } // Draw bottom line, if requested if (lastLine) { g.DrawLine(thickPen, new PointF(0, 100), new PointF(fullWidth, 100)); } // Draw side lines. float lineTop = -PunchcardAppearance.thickLine / 2; float lineBottom = 100 + PunchcardAppearance.thickLine / 2; g.DrawLine(thickPen, new PointF(0, lineTop), new PointF(0, lineBottom)); g.DrawLine(thickPen, new PointF(fullWidth, lineTop), new PointF(fullWidth, lineBottom)); if (line == 0) { // Draw title RectangleF rect = new RectangleF(0, 0, fullWidth, 100); StringFormat stringFormat = new StringFormat(StringFormat.GenericDefault); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; stringFormat.FormatFlags = StringFormatFlags.NoWrap; DrawSingleLineText(g, courseView.CourseFullName, PunchcardAppearance.titleFont, rect.Center(), StringAlignment.Center, StringAlignment.Center); } else { // Draw grid lines and the boxes. for (int col = 0; col < punchcardFormat.boxesAcross; ++col) { if (col != 0) { g.DrawLine(thinPen, new PointF(100 * col, lineTop), new PointF(100 * col, lineBottom)); } RectangleF boxRect = new RectangleF(100 * col, 0, 100, 100); // Figure out the box number (0 based!) int lineStart, boxWithinLine, boxNumber; if (punchcardFormat.topToBottom) { lineStart = (line - 1) * punchcardFormat.boxesAcross; } else { lineStart = (lineCount - line) * punchcardFormat.boxesAcross; } if (punchcardFormat.leftToRight) { boxWithinLine = col; } else { boxWithinLine = (punchcardFormat.boxesAcross - col - 1); } boxNumber = lineStart + boxWithinLine; if (boxNumber < boxes.Count) { RenderPunchBox(g, boxes[boxNumber], boxRect); } } } }
private void PushRectangleClip(IGraphicsTarget graphicsTarget, RectangleF rect) { object rectanglePath = new object(); graphicsTarget.CreatePath(rectanglePath, new List<GraphicsPathPart> { new GraphicsPathPart(GraphicsPathPartKind.Start, new PointF[] { rect.Location }), new GraphicsPathPart(GraphicsPathPartKind.Lines, new PointF[] { new PointF(rect.Right, rect.Top), new PointF(rect.Right, rect.Bottom), new PointF(rect.Left, rect.Bottom), new PointF(rect.Left, rect.Top)}), new GraphicsPathPart(GraphicsPathPartKind.Close, new PointF[0]) }, FillMode.Winding); graphicsTarget.PushClip(rectanglePath); }
// Draw the bitmap map part. void DrawBitmapMap(IGraphicsTarget grTarget, RectangleF visRect, float minResolution) { // Setup transform. grTarget.PushTransform(BitmapTransform()); // Setup drawing map and intensity. BitmapScaling scalingMode = antialiased ? BitmapScaling.MediumQuality : BitmapScaling.NearestNeighbor; if (bitmap.PixelHeight * bitmap.PixelWidth > 50000000) scalingMode = BitmapScaling.NearestNeighbor; // Turn off high quality scaling for very large bitmaps. // Get source bitmap. Use the dimmed bitmap if there is one. IGraphicsBitmap sourceBitmap; if (dimmedBitmap != null) sourceBitmap = dimmedBitmap; else sourceBitmap = bitmap; // Draw it. grTarget.DrawBitmap(sourceBitmap, new RectangleF(0, 0, bitmap.PixelWidth, bitmap.PixelHeight), scalingMode, minResolution); if (mapIntensity < 0.99 && sourceBitmap == bitmap) { // Dimming desired, but we don't have a dimmed bitmap. Use an alpha mask instead. CmykColor dimmedWhite = CmykColor.FromCmyka(0, 0, 0, 0, 1-mapIntensity); object brush = new object(); grTarget.CreateSolidBrush(brush, dimmedWhite); grTarget.FillRectangle(brush, new RectangleF(0, 0, bitmap.PixelWidth, bitmap.PixelHeight)); } // Pop transform grTarget.PopTransform(); }
// The core printing routine. The origin of the graphics is the upper-left of the margins, // and the printArea in the size to draw into (in hundreths of an inch). protected override void DrawPage(IGraphicsTarget graphicsTarget, int pageNumber, SizeF printArea, float dpi) { //Graphics g = ((GDIPlus_GraphicsTarget)graphicsTarget).Graphics; //positioner.DrawPage(g, pageNumber); positioner.DrawPage(graphicsTarget, pageNumber); }
// Draw the ocad map part. void DrawOcadMap(IGraphicsTarget grTarget, RectangleF visRect, RenderOptions renderOptions) { using (map.Write()) { map.Draw(grTarget, visRect, renderOptions, null); } }
// Create a single PDF file void CreateOnePdfFile(string fileName, IEnumerable <CourseDesignator> courseDesignators) { List <CoursePage> pages = LayoutPages(courseDesignators); PdfWriter pdfWriter = new PdfWriter(Path.GetFileNameWithoutExtension(fileName), coursePdfSettings.ColorModel == ColorModel.CMYK); IGraphicsTarget grTarget = null; foreach (CoursePage page in pages) { CoursePage pageToDraw = page; SizeF paperSize = new SizeF(pageToDraw.paperSize.Width / 100F, pageToDraw.paperSize.Height / 100F); if (pageToDraw.landscape) { paperSize = new SizeF(paperSize.Height, paperSize.Width); } if (controller.UpdateProgressDialog(string.Format(MiscText.CreatingFile, Path.GetFileName(fileName)), (double)currentPage / (double)totalPages)) { throw new Exception(MiscText.CancelledByUser); } PdfImporter pdfImporter = null; if (IsPdfMap) { // We need to re-obtain a PdfImporter every time, or else very strange bugs start to crop up. pdfImporter = new PdfImporter(sourcePdfMapFileName); float scaleRatio = CourseView.CreatePrintingCourseView(eventDB, page.courseDesignator).ScaleRatio; if (scaleRatio == 1.0) { // If we're doing a PDF at scale 1, we just copy the page directly. grTarget = pdfWriter.BeginCopiedPage(pdfImporter, 0); pageToDraw = PdfNonScaledPage(page.courseDesignator); } else { Matrix transform = Geometry.CreateInvertedRectangleTransform(page.printRectangle, page.mapRectangle); RectangleF printedPortionInMapCoords = Geometry.TransformRectangle(transform, new RectangleF(0, 0, paperSize.Width * 100F, paperSize.Height * 100F)); RectangleF printedPortionInInches = new RectangleF( Geometry.InchesFromMm(printedPortionInMapCoords.Left), Geometry.InchesFromMm(mapBounds.Height - printedPortionInMapCoords.Bottom), Geometry.InchesFromMm(printedPortionInMapCoords.Width), Geometry.InchesFromMm(printedPortionInMapCoords.Height)); grTarget = pdfWriter.BeginCopiedPartialPage(pdfImporter, 0, paperSize, printedPortionInInches); } // Don't draw the map normally. mapDisplay.SetMapFile(MapType.None, null); } else { if (page.startNewPage || grTarget == null) { if (grTarget != null) { pdfWriter.EndPage(grTarget); grTarget.Dispose(); grTarget = null; } grTarget = pdfWriter.BeginPage(paperSize); } } DrawPage(grTarget, pageToDraw); if (pdfImporter != null) { pdfImporter.Dispose(); pdfImporter = null; } currentPage += 1; } if (grTarget != null) { pdfWriter.EndPage(grTarget); grTarget.Dispose(); grTarget = null; } pdfWriter.Save(fileName); }