public void HintGlyph(PointF[] glyphPoints, int[] contours, byte[] instructions) { if (instructions == null || instructions.Length == 0) return; // check if the CVT program disabled hinting if ((state.InstructionControl & InstructionControlFlags.InhibitGridFitting) != 0) return; // TODO: composite glyphs // TODO: round the phantom points? // save contours and points this.contours = contours; zp0 = zp1 = zp2 = points = new Zone(glyphPoints, isTwilight: false); // reset all of our shared state state = cvtState; callStackSize = 0; debugList.Clear(); stack.Clear(); OnVectorsUpdated(); // normalize the round state settings switch (state.RoundState) { case RoundMode.Super: SetSuperRound(1.0f); break; case RoundMode.Super45: SetSuperRound(Sqrt2Over2); break; } Execute(new InstructionStream(instructions), false, false); }
public static void DecomposeContour(SharpFontRenderer renderer, int firstIndex, int lastIndex, PointF[] points) { var pointIndex = firstIndex; var start = points[pointIndex]; var end = points[lastIndex]; var control = start; if (start.Type == PointType.Cubic) throw new Exception("Contours can't start with a cubic control point."); if (start.Type == PointType.Quadratic) { // if first point is a control point, try using the last point if (end.Type == PointType.OnCurve) { start = end; lastIndex--; } else { // if they're both control points, start at the middle start.P = (start.P + end.P) / 2; } pointIndex--; } // let's draw this contour renderer.MoveTo(start); var needClose = true; while (pointIndex < lastIndex) { var point = points[++pointIndex]; switch (point.Type) { case PointType.OnCurve: renderer.LineTo(point); break; case PointType.Quadratic: control = point; var done = false; while (pointIndex < lastIndex) { var next = points[++pointIndex]; if (next.Type == PointType.OnCurve) { renderer.QuadraticCurveTo(control, next); done = true; break; } if (next.Type != PointType.Quadratic) throw new Exception("Bad outline data."); renderer.QuadraticCurveTo(control, (control.P + next.P) / 2); control = next; } if (!done) { // if we hit this point, we're ready to close out the contour renderer.QuadraticCurveTo(control, start); needClose = false; } break; case PointType.Cubic: throw new NotSupportedException(); } } if (needClose) renderer.LineTo(start); }
public Zone(PointF[] points, bool isTwilight) { IsTwilight = isTwilight; Current = points; Original = (PointF[])points.Clone(); TouchState = new TouchState[points.Length]; }
internal Glyph(Renderer renderer, PointF[] points, int[] contours, float linearHorizontalAdvance) { this.renderer = renderer; this.points = points; this.contours = contours; // find the bounding box var min = new Vector2(float.MaxValue, float.MaxValue); var max = new Vector2(float.MinValue, float.MinValue); var pointCount = points.Length - 4; for (int i = 0; i < pointCount; i++) { min = Vector2.Min(min, points[i].P); max = Vector2.Max(max, points[i].P); } // save the "pure" size of the glyph, in fractional pixels var size = max - min; Width = size.X; Height = size.Y; // find the "render" size of the glyph, in whole pixels var shiftX = (int)Math.Floor(min.X); var shiftY = (int)Math.Floor(min.Y); RenderWidth = (int)Math.Ceiling(max.X) - shiftX; RenderHeight = (int)Math.Ceiling(max.Y) - shiftY; // translate the points so that 0,0 is at the bottom left corner var offset = new Vector2(-shiftX, -shiftY); for (int i = 0; i < pointCount; i++) points[i] = points[i].Offset(offset); HorizontalMetrics = new GlyphMetrics(new Vector2(min.X, max.Y), points[pointCount + 1].P.X - points[pointCount].P.X, linearHorizontalAdvance); // TODO: vertical metrics }