Beispiel #1
0
        // Create a single PDF file
        void CreateOneBitmap(string fileName, CourseDesignator courseDesignator)
        {
            RectangleF mapRectangle = controller.GetCurrentPrintAreaRectangle(courseDesignator);

            // Get the course view for the course we are printing.
            CourseView courseView = CourseView.CreatePrintingCourseView(eventDB, 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);

            ExportBitmap exportBitmap = new ExportBitmap(mapDisplay);

            exportBitmap.CreateBitmap(fileName, mapRectangle, GetImageFormat(), bitmapCreationSettings.Dpi,
                                      bitmapCreationSettings.WorldFile ? mapDisplay.CoordinateMapper : null);
        }
        private TopologyDropTargetCourseObj FindNearbyDropTarget(PointF location)
        {
            const float MAXDISTANCE = 9F;
            const float MINDRAGDIST = 5F;

            CourseLayout layout = selectionMgr.TopologyLayout;
            TopologyDropTargetCourseObj nearest           = null;
            Id <CourseControl>          courseControlDrag = courseObjectDrag.courseControlId;
            float nearestDistance = float.MaxValue;

            // Find nearest drop target that is within MAXDISTANCE of location, and not adjacent to the
            // course control we are dragging.
            foreach (CourseObj obj in layout)
            {
                TopologyDropTargetCourseObj dropTarget = obj as TopologyDropTargetCourseObj;
                if (dropTarget != null &&
                    ((dropTarget.courseControlId != courseControlDrag && dropTarget.courseControlId2 != courseControlDrag) ||
                     courseObjectStart.DistanceFromPoint(dropTarget.location) > MINDRAGDIST))
                {
                    float distance = Geometry.DistanceF(location, dropTarget.location);
                    if (distance < nearestDistance && distance < MAXDISTANCE)
                    {
                        nearestDistance = distance;
                        nearest         = dropTarget;
                    }
                }
            }

            return(nearest);
        }
Beispiel #3
0
        // Format the given CourseView into a bunch of course objects, and add it to the given course Layout
        public RectangleF FormatCourseToLayout(SymbolDB symbolDB, CourseView courseViewAllVariations, CourseView specificVariation, CourseLayout courseLayout,
                                               Id <CourseControl> ccSelection1, Id <CourseControl> ccSelection2, CourseLayer layerAllVariations, CourseLayer layerSpecificVariation)
        {
            this.eventDB      = courseViewAllVariations.EventDB;
            this.symbolDB     = symbolDB;
            this.courseLayout = courseLayout;
            this.courseLayerAllVariationsAndParts  = layerAllVariations;
            this.courseLayerSpecificVariation      = layerSpecificVariation;
            this.controlViewsAllVariationsAndParts = courseViewAllVariations.ControlViews;
            this.controlViewsSpecificVariation     = specificVariation.ControlViews;
            this.controlPositions = new ControlPosition[controlViewsAllVariationsAndParts.Count];
            this.courseControlIdsSpecificVariation = QueryEvent.EnumCourseControlIds(eventDB, specificVariation.CourseDesignator).ToArray();
            this.courseControlIdSelection1         = ccSelection1;
            this.courseControlIdSelection2         = ccSelection2;
            this.variationMap = QueryEvent.GetVariantCodeMapping(eventDB, courseViewAllVariations.CourseDesignator);

            SizeF totalAbstractSize = AssignControlPositions(0, controlViewsAllVariationsAndParts.Count, 0, 0);

            // Now create objects now that the positions have been created.
            courseObjRatio = 1.0F;
            appearance     = new CourseAppearance();

            for (int index = 0; index < controlViewsAllVariationsAndParts.Count; ++index)
            {
                CreateObjectsForControlView(controlViewsAllVariationsAndParts[index], controlPositions[index]);
            }

            PointF     bottomCenter = LocationFromAbstractPosition(0, 0);
            SizeF      size         = SizeFromAbstractSize(totalAbstractSize);
            RectangleF rect         = new RectangleF(bottomCenter.X - size.Width / 2, bottomCenter.Y - size.Height, size.Width, size.Height);

            rect.Inflate(widthUnit, heightUnit);
            return(rect);
        }
Beispiel #4
0
        CourseLayout CreateCourseLayout(CourseView courseView)
        {
            // Create the CourseLayout.
            CourseLayout courseLayout = new CourseLayout();

            courseLayout.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
            courseLayout.SetLayerColor(CourseLayer.MainCourse, NormalCourseAppearance.courseOcadId, NormalCourseAppearance.courseColorName,
                                       creationSettings.cyan, creationSettings.magenta, creationSettings.yellow, creationSettings.black, creationSettings.purpleOverprint);
            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, courseAppearance, courseLayout, CourseLayer.MainCourse);

            return(courseLayout);
        }
Beispiel #5
0
 // Update the topology
 void UpdateTopology()
 {
     if (topologyCourseView == null) {
         activeTopologyCourseLayout = null;
     }
     else {
         // Place the active course in the layout.
         activeTopologyCourseLayout = new CourseLayout();
         activeTopologyCourseLayout.SetLayerColor(CourseLayer.AllVariations, 1, NormalCourseAppearance.blackColorName, 0, 0, 0, 0.55F, false);
         activeTopologyCourseLayout.SetLayerColor(CourseLayer.MainCourse, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
         activeTopologyCourseLayout.SetLayerColor(CourseLayer.InvisibleObjects, 2, "DropTargets", 0, 0, 0, 0, false);
         TopologyFormatter formatter = new TopologyFormatter();
         formatter.FormatCourseToLayout(symbolDB, topologyCourseView, activeCourseView, activeTopologyCourseLayout, selectedCourseControl, selectedCourseControl2, CourseLayer.AllVariations, CourseLayer.MainCourse);
     }
 }
Beispiel #6
0
        // Left mouse button selects the object clicked on, or drag something already selected.
        public override MapViewer.DragAction LeftButtonDown(Pane pane, PointF location, float pixelSize, ref bool displayUpdateNeeded)
        {
            if (pane == Pane.Map)
            {
                CourseLayout activeCourse = controller.GetCourseLayout();
                CourseObj    clickedObject;
                PointF       handleLocation;
                Cursor       handleCursor;

                // Area we initiating a drag of a corner?
                clickedObject = HitTestHandle(location, pixelSize, out handleLocation, out handleCursor);
                if (clickedObject != null)
                {
                    // being dragging the corner
                    DragHandleMode commandMode = new DragHandleMode(controller, clickedObject, handleLocation, location);
                    controller.SetCommandMode(commandMode);
                    displayUpdateNeeded = true;
                    return(MapViewer.DragAction.ImmediateDrag);
                }

                // Are we initiating a drag of an object?
                clickedObject = HitTestDraggable(location, pixelSize);
                if (clickedObject != null)
                {
                    // Begin dragging the clicked object.
                    DragObjectMode commandMode = new DragObjectMode(controller, eventDB, selectionMgr, clickedObject, location);
                    controller.SetCommandMode(commandMode);
                    displayUpdateNeeded = true;
                    return(MapViewer.DragAction.ImmediateDrag);
                }

                return(MapViewer.DragAction.DelayedDrag);
            }
            else if (pane == Pane.Topology)
            {
                CourseObj clickedObject = HitTest(pane, location, pixelSize, (co => !(co is TopologyDropTargetCourseObj)));
                if (clickedObject is ControlNumberCourseObj || clickedObject is CrossingCourseObj ||
                    (clickedObject is StartCourseObj && (eventDB.GetControl(((StartCourseObj)clickedObject).controlId).kind == ControlPointKind.MapExchange)))
                {
                    // Can drag control numbers, crossing points, or map exchanges.
                    selectionMgr.SelectCourseObject(clickedObject);
                    displayUpdateNeeded = true;
                    return(MapViewer.DragAction.DelayedDrag);
                }
            }

            return(MapViewer.DragAction.None);
        }
Beispiel #7
0
        // Hit test a location to see if it is over a selected, draggable objects. If so,
        // return that course object, otherwise, return null.
        CourseObj HitTestDraggable(PointF location, float pixelSize)
        {
            CourseObj[] selectedObjects = selectionMgr.SelectedCourseObjects;

            if (selectedObjects != null)
            {
                // If the cursor is above a selected control, start, finish that is a moveable object.
                CourseObj hitObject = CourseLayout.HitTestCollection(selectedObjects, location, pixelSize, CourseLayer.All, null);
                if (hitObject != null && DraggableObject(hitObject))
                {
                    return(hitObject);
                }
            }

            return(null);
        }
Beispiel #8
0
        // Hit test a point to see if it is over an existing control, or will create a new control.
        Id <ControlPoint> HitTestPoint(PointF mouseLocation, float pixelSize, out PointF highlightLocation)
        {
            if (allControls)
            {
                // If all controls, always new control.
                highlightLocation = new PointF(mouseLocation.X + PIXELOFFSETX * pixelSize, mouseLocation.Y + PIXELOFFSETY * pixelSize);
                return(Id <ControlPoint> .None);
            }
            else
            {
                // Are we over a control we might add?
                CourseLayout   layout    = controller.GetCourseLayout();
                PointCourseObj courseObj = layout.HitTest(mouseLocation, pixelSize, CourseLayer.AllControls, (co => co is PointCourseObj)) as PointCourseObj;
                if (courseObj != null)
                {
                    highlightLocation = courseObj.location;
                    return(courseObj.controlId);
                }
                else
                {
                    courseObj = layout.HitTest(mouseLocation, pixelSize, CourseLayer.MainCourse, (co => co is PointCourseObj)) as PointCourseObj;
                    if (courseObj != null &&
                        courseObj.controlId.IsNotNone)
                    {
                        // Allow selecting a control in the current course for a butterfly course. But -- it must be a normal control or crossing point, and not adjacent to the control being inserted.
                        if (eventDB.GetControl(courseObj.controlId).kind == controlKind && (controlKind == ControlPointKind.Normal || controlKind == ControlPointKind.CrossingPoint))
                        {
                            Id <CourseControl> courseControl1, courseControl2;
                            CourseDesignator   courseDesignator;
                            LegInsertionLoc    legInsertionLoc;

                            GetControlInsertionPoint(courseObj.location, out courseDesignator, out courseControl1, out courseControl2, out legInsertionLoc);
                            if (eventDB.GetCourse(courseDesignator.CourseId).kind != CourseKind.Score &&
                                (exchangeAtControl ||
                                 (courseObj.courseControlId != courseControl1 && courseObj.courseControlId != courseControl2)))
                            {
                                highlightLocation = courseObj.location;
                                return(courseObj.controlId);
                            }
                        }
                    }

                    highlightLocation = new PointF(mouseLocation.X + PIXELOFFSETX * pixelSize, mouseLocation.Y + PIXELOFFSETY * pixelSize);
                    return(Id <ControlPoint> .None);
                }
            }
        }
Beispiel #9
0
        private CourseObj HitTest(Pane pane, PointF location, float pixelSize, Predicate <CourseObj> filter)
        {
            CourseLayout activeCourse = (pane == Pane.Map) ? controller.GetCourseLayout() : controller.GetTopologyLayout();
            CourseObj    clickedObject;

            clickedObject = activeCourse.HitTest(location, pixelSize, CourseLayer.MainCourse, filter);
            if (clickedObject == null)
            {
                clickedObject = activeCourse.HitTest(location, pixelSize, CourseLayer.Descriptions, filter);
            }
            if (clickedObject == null && pane == Pane.Topology)
            {
                clickedObject = activeCourse.HitTest(location, pixelSize, CourseLayer.AllVariations, filter);
            }

            return(clickedObject);
        }
Beispiel #10
0
        // Set the courses being displayed.
        public void SetCourse(CourseLayout newCourse)
        {
            if (!object.Equals(course, newCourse))
            {
                course = newCourse;
                if (course == null)
                {
                    courseMap = null;
                }
                else
                {
                    courseMap = course.RenderToMap(new CourseLayout.MapRenderOptions());
                }

                RaiseChanged(null);
            }
        }
Beispiel #11
0
        // Determine if two course layouts are equal. Important because is can prevent expensive redraws of the course.
        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is CourseLayout))
            {
                return(false);
            }

            if ((object)this == obj)
            {
                return(true);              // identical objects are equal.
            }
            CourseLayout other = (CourseLayout)obj;

            for (int i = 0; i < LAYERCOUNT; i++)
            {
                if (other.colorC[i] != colorC[i] || other.colorK[i] != colorK[i] || other.colorM[i] != colorM[i] || other.colorY[i] != colorY[i] || other.colorOverprint[i] != colorOverprint[i])
                {
                    return(false);
                }
                if (other.ocadColorId[i] != ocadColorId[i] || other.colorName[i] != colorName[i])
                {
                    return(false);
                }
            }

            List <CourseObj> otherList = other.objects;

            if (otherList.Count != objects.Count)
            {
                return(false);
            }

            for (int i = 0; i < objects.Count; ++i)
            {
                if (!(objects[i].Equals(otherList[i])))
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #12
0
        // 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();
        }
Beispiel #13
0
        // Update the course
        void UpdateCourse()
        {
            CourseAppearance appearance = controller.GetCourseAppearance();

            // Get purple color.
            short purpleOcadId;
            float purpleC, purpleM, purpleY, purpleK;
            bool purpleOverprint;
            controller.GetPurpleColor(out purpleOcadId, out purpleC, out purpleM, out purpleY, out purpleK, out purpleOverprint);

            // Place the active course in the layout.
            activeCourse = new CourseLayout();
            activeCourse.SetLayerColor(CourseLayer.Descriptions, NormalCourseAppearance.blackColorOcadId, NormalCourseAppearance.blackColorName, NormalCourseAppearance.blackColorC, NormalCourseAppearance.blackColorM, NormalCourseAppearance.blackColorY, NormalCourseAppearance.blackColorK, false);
            activeCourse.SetLayerColor(CourseLayer.MainCourse, NormalCourseAppearance.courseOcadId, NormalCourseAppearance.courseColorName, purpleC, purpleM, purpleY, purpleK, 
                                       (purpleOverprint && (extraCourses == null || extraCourses.Count == 0))); 
            CourseFormatter.FormatCourseToLayout(symbolDB, activeCourseView, appearance, activeCourse, CourseLayer.MainCourse);

            if (showAllControls && !activeCourseDesignator.IsAllControls) {
                // Create the all controls view.
                CourseView allControlsView = CourseView.CreateFilteredAllControlsView(eventDB, new CourseDesignator[] { activeCourseDesignator }, allControlsFilter, 
                    new CourseViewOptions() { showNonDescriptionSpecials = false, showDescriptionSpecials = false });

                // Add it to the CourseLayout.
                activeCourse.SetLayerColor(CourseLayer.AllControls, NormalCourseAppearance.allControlsOcadId, NormalCourseAppearance.allControlsColorName,
                    NormalCourseAppearance.allControlsColorC, NormalCourseAppearance.allControlsColorM, NormalCourseAppearance.allControlsColorY, NormalCourseAppearance.allControlsColorK, purpleOverprint);
                CourseFormatter.FormatCourseToLayout(symbolDB, allControlsView, appearance, activeCourse, CourseLayer.AllControls);
            }

            if (extraCourses != null && extraCourses.Count > 0) {
                for (int i = 0; i < extraCourses.Count; ++i) {
                    Id<Course> courseId = extraCourses[i];
                    if (eventDB.IsCoursePresent(courseId)) {
                        AddExtraCourseToLayout(activeCourse, courseId, i % CourseLayout.EXTRACOURSECOUNT);
                    }
                }
            }
        }
Beispiel #14
0
        // extraCourseIndex indicates the color/layer.
        private void AddExtraCourseToLayout(CourseLayout courseLayout, Id<Course> courseId, int extraCourseIndex)
        {
            if (extraCourseIndex >= CourseLayout.EXTRACOURSECOUNT)
                return;

            CourseAppearance appearance = controller.GetCourseAppearance();
            CourseLayer layer = CourseLayer.OtherCourse1 + extraCourseIndex;

            // Create the course view.
            CourseView courseView = CourseView.CreateCourseView(eventDB, new CourseDesignator(courseId),
                new CourseViewOptions() { showNonDescriptionSpecials = false, showDescriptionSpecials = false, showControlNumbers = false });

            // Add it to the CourseLayout.
            courseLayout.SetLayerColor(layer, (short) (NormalCourseAppearance.extraCourseOcadId + extraCourseIndex), 
                                              string.Format(NormalCourseAppearance.allControlsColorName, extraCourseIndex + 1),
                                              NormalCourseAppearance.extraCourseC[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseM[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseY[extraCourseIndex],
                                              NormalCourseAppearance.extraCourseK[extraCourseIndex],
                                              false);

            CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, courseLayout, layer,
                new CourseFormatterOptions() { showControlNumbers = false });
        }
Beispiel #15
0
        // Get the area of the map we want to print, in map coordinates, and the print scale.
        // if the courseId is None, do all controls.
        // If asked for, crop to a single page size.
        RectangleF GetPrintAreaForCourse(CourseDesignator courseDesignator, out bool landscape, out PaperSize paperSize, out int margins, out float scaleRatio, out string description)
        {
            // Get the course view to get the scale ratio.
            CourseView courseView = CourseView.CreatePositioningCourseView(eventDB, courseDesignator);

            scaleRatio  = courseView.ScaleRatio;
            description = courseView.CourseFullName;

            RectangleF printRectangle = controller.GetCurrentPrintAreaRectangle(courseDesignator);
            PrintArea  printArea      = controller.GetCurrentPrintArea(courseDesignator);

            landscape = printArea.pageLandscape;
            paperSize = new PaperSize("", printArea.pageWidth, printArea.pageHeight);
            margins   = printArea.pageMargins;

            if (cropLargePrintArea)
            {
                // Crop the print area to a single page, portrait or landscape.
                // Try to keep CourseObjects in view as much as possible.
                CourseLayout layout = new CourseLayout();
                CourseFormatter.FormatCourseToLayout(symbolDB, courseView, appearance, layout, 0);
                RectangleF courseObjectsArea = layout.BoundingRect();
                courseObjectsArea.Intersect(printRectangle);

                // We may need to crop the print area to fit.
                float      areaCovered;
                RectangleF printableArea    = GetPrintablePageArea(landscape, paperSize, margins);
                RectangleF croppedRectangle = CropPrintArea(printRectangle, courseObjectsArea, GetScaledPrintableSizeInMapUnits(printableArea, scaleRatio), out areaCovered);

                return(croppedRectangle);
            }
            else
            {
                return(printRectangle);
            }
        }
Beispiel #16
0
        // Write a map to the given file name.
        void ExportMap(CourseView courseView, string outputFilename)
        {
            // Create the CourseLayout.
            CourseLayout courseLayout = CreateCourseLayout(courseView);

            // OCAD 6-10 cannot handle images in the layout layer, and OOM doesn't have a layout layer.
            CourseLayout.MapRenderOptions mapRenderOptions = new CourseLayout.MapRenderOptions();
            if ((creationSettings.fileFormat.kind == MapFileFormatKind.OCAD && creationSettings.fileFormat.version <= 10) ||
                creationSettings.fileFormat.kind == MapFileFormatKind.OpenMapper)
            {
                mapRenderOptions.RenderImagesAsTemplates = true;
            }
            else
            {
                mapRenderOptions.RenderImagesAsTemplates = false;
            }

            // Create the map and write it out.
            Map map = courseLayout.RenderToMap(mapRenderOptions);

            using (map.Write()) {
                map.MapScale   = courseView.MapScale;
                map.PrintScale = courseView.PrintScale;
                map.PrintArea  = controller.GetCurrentPrintAreaRectangle(courseView.CourseDesignator);

                switch (controller.MapType)
                {
                case MapType.OCAD:
                    // Set OCAD map as template.
                    // OCAD 6 doesn't support another OCAD file as a template.
                    if (!(creationSettings.fileFormat.kind == MapFileFormatKind.OCAD && creationSettings.fileFormat.version <= 6))
                    {
                        AddTemplateToMap(map, new TemplateInfo(controller.MapFileName, new PointF(0, 0), 0, 0, true));
                    }

                    // Use same real world coordinates as underlying map (nicer, but also works around bug in OCAD 11
                    // where background maps with real world coordinates aren't displayed if the map map doesn't have same real
                    // world coordinates).
                    map.RealWorldCoords = controller.MapRealWorldCoords;
                    break;

                case MapType.Bitmap:
                case MapType.PDF:
                    // Set bitmap as template.
                    PointF centerPoint = Geometry.RectCenter(controller.MapDisplay.MapBounds);

                    ImageFormat imageFormat;
                    string      mapFileName;
                    float       dpi;
                    if (CreateBitmapFile())
                    {
                        // Write a copy of the bitmap map.
                        mapFileName = CreateBitmapFileName(out imageFormat);
                        controller.MapDisplay.WriteBitmapMap(mapFileName, imageFormat, out dpi);
                    }
                    else
                    {
                        // Use existing map file.
                        mapFileName = controller.MapFileName;
                        dpi         = controller.MapDpi;
                    }

                    AddTemplateToMap(map, new TemplateInfo(mapFileName, centerPoint, dpi, 0, true));
                    break;

                case MapType.None:
                    break;

                default:
                    Debug.Fail("Unexpected map type");
                    break;
                }
            }

            WriteImageBitmaps(map);

            InputOutput.WriteFile(outputFilename, map, creationSettings.fileFormat);
        }
Beispiel #17
0
        // 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();
            }
        }