void InternalDrawString(char[] textBuffer, int startAt, int len, float x, float y) { UpdateGlyphLayoutSettings(); //unscale layout, with design unit scale _glyphLayout.Layout(textBuffer, startAt, len); // // // if (this._pxScaleEngine != null) { _outputPxScaledGlyphPlans.Clear(); //scale to specific font size _pxScaleEngine.Layout(_glyphLayout.ResultUnscaledGlyphPositions, _outputPxScaledGlyphPlans); DrawFromGlyphPlans(_outputPxScaledGlyphPlans, x, y); } else { _outputUnscaledGlyphPlans.Clear(); //no custom engine //then use default scale GlyphLayoutExtensions.GenerateGlyphPlans( _glyphLayout.ResultUnscaledGlyphPositions, _currentFontSizePxScale, false, _outputPxScaledGlyphPlans); DrawFromGlyphPlans(_outputUnscaledGlyphPlans, x, y); } }
public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y) { _reusableUnscaledGlyphPlanList.Clear(); //1. unscale layout, in design unit _glyphLayout.Layout(textBuffer, startAt, len); _glyphLayout.GenerateUnscaledGlyphPlans(_reusableUnscaledGlyphPlanList); //draw from the glyph plan seq DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x, y); }
} // End Sub DrawFromGlyphPlans public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y) { this.TargetGraphics.SetTextAndFont(new string(textBuffer), this.Typeface.Name, this.FontSizeInPoints); this.TargetGraphics.OpenGroup(); _reusableUnscaledGlyphPlanList.Clear(); //1. unscale layout, in design unit _glyphLayout.Layout(textBuffer, startAt, len); _glyphLayout.GenerateUnscaledGlyphPlans(_reusableUnscaledGlyphPlanList); //draw from the glyph plan seq DrawFromGlyphPlans(new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x, y); this.TargetGraphics.CloseGroup(); } // End Sub DrawString
public void Draw() { //List<UserCodePointToGlyphIndex> userCharToGlyphIndexMap = _line._userCodePointToGlyphIndexMap; if (_line.ContentChanged) { //TODO: or font face/font-size change //re-calculate char[] textBuffer = _line._charBuffer.ToArray(); //userCharToGlyphIndexMap.Clear(); //read glyph plan and userCharToGlyphIndexMap _reusableUnscaledGlyphPlanList.Clear(); _printer.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList); _line.ContentChanged = false; } if (_reusableUnscaledGlyphPlanList.Count > 0) { _printer.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), X, Y); //draw caret //not blink in this version int caret_index = _line.CaretCharIndex; //find caret pos based on glyph plan //TODO: check when do gsub (glyph number may not match with user char number) if (caret_index == 0) { //_printer.DrawCaret(X, this.Y); } else { //UserCodePointToGlyphIndex map = userCharToGlyphIndexMap[caret_index - 1]; //GlyphPlan p = glyphPlans[map.glyphIndexListOffset_plus1 + map.len - 2]; //_printer.DrawCaret(X + (p.ExactX + p.AdvanceX), this.Y); } } else { //_printer.DrawCaret(X, this.Y); } }
public override void DrawString(char[] textBuffer, int startAt, int len, float x, float y) { //---------------- //TODO: use typography text service //it should be faster since it has glyph-plan cache //---------------- //1. update UpdateGlyphLayoutSettings(); //2. unscale layout, in design unit this._glyphLayout.Layout(textBuffer, startAt, len); //3. scale to specific font size _resuableGlyphPlanList.Clear(); GlyphLayoutExtensions.GenerateGlyphPlans( _glyphLayout.ResultUnscaledGlyphPositions, _currentTypeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints), false, _reusablePxScaleGlyphPlanList); DrawFromGlyphPlans(_resuableGlyphPlanList, x, y); }
private void cmdMeasureTextSpan_Click(object sender, System.EventArgs e) { //set some Gdi+ props... g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(Color.White); //credit: //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly //-------------------------------- //textspan measurement sample //-------------------------------- _currentTextPrinter.HintTechnique = (HintTechnique)lstHintList.SelectedItem; _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem; //render at specific pos float x_pos = 0, y_pos = 100; char[] textBuffer = txtInputChar.Text.ToCharArray(); //Example 1: this is a basic draw sample _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.TargetGraphics = g; _currentTextPrinter.DrawString( textBuffer, 0, textBuffer.Length, x_pos, y_pos ); // //-------------------------------------------------- //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw) //you can create you own class to hold userGlyphPlans.*** //2.1 _reusableUnscaledGlyphPlan.Clear(); _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlan); //2.2 //and we can print the formatted glyph plan later. y_pos -= _currentTextPrinter.FontLineSpacingPx; _currentTextPrinter.FillColor = Color.Red; _currentTextPrinter.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlan), x_pos, y_pos ); //Example 3: MeasureString //TODO: review here again MeasuredStringBox strBox = _currentTextPrinter.GlyphLayoutMan.LayoutAndMeasureString( textBuffer, 0, textBuffer.Length, _currentTextPrinter.FontSizeInPoints); //draw line mark float x_pos2 = x_pos + strBox.width + 10; g.DrawRectangle(Pens.Red, x_pos, y_pos, strBox.width, strBox.LineSpaceInPx); g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos); //baseline g.DrawLine(Pens.Green, x_pos, y_pos + strBox.DescendingInPx, x_pos2, y_pos + strBox.DescendingInPx); //descending g.DrawLine(Pens.Magenta, x_pos, y_pos + strBox.AscendingInPx, x_pos2, y_pos + strBox.AscendingInPx); //ascending _currentTextPrinter.FillColor = Color.Black; //transform back g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly }
/// <summary> /// generate glyph run into a given textRun /// </summary> /// <param name="outputTextRun"></param> /// <param name="charBuffer"></param> /// <param name="start"></param> /// <param name="len"></param> public void GenerateGlyphRuns(TextRun outputTextRun, char[] charBuffer, int start, int len) { // layout glyphs with selected layout technique float sizeInPoints = this.FontSizeInPoints; outputTextRun.typeface = this.Typeface; outputTextRun.sizeInPoints = sizeInPoints; //in this version we store original glyph into the mesh collection //and then we scale it later, so I just specific font size=0 (you can use any value) _glyphMeshCollection.SetCacheInfo(this.Typeface, 0, this.HintTechnique); GlyphLayoutMan.Typeface = this.Typeface; GlyphLayoutMan.Layout(charBuffer, start, len); float pxscale = this.Typeface.CalculateScaleToPixelFromPointSize(sizeInPoints); _resuableGlyphPlanList.Clear(); GenerateGlyphPlan(charBuffer, 0, charBuffer.Length, _resuableGlyphPlanList); // render each glyph int planCount = _resuableGlyphPlanList.Count; for (var i = 0; i < planCount; ++i) { _pathTranslator.Reset(); //---- //glyph path //---- UnscaledGlyphPlan glyphPlan = _resuableGlyphPlanList[i]; // //1. check if we have this glyph in cache? //if yes, not need to build it again ProcessedGlyph processGlyph; float[] tessData = null; if (!_glyphMeshCollection.TryGetCacheGlyph(glyphPlan.glyphIndex, out processGlyph)) { //if not found the create a new one and register it var writablePath = new WritablePath(); _pathTranslator.SetOutput(writablePath); _currentGlyphPathBuilder.BuildFromGlyphIndex(glyphPlan.glyphIndex, sizeInPoints); _currentGlyphPathBuilder.ReadShapes(_pathTranslator); //------- //do tess int[] endContours; float[] flattenPoints = _curveFlattener.Flatten(writablePath._points, out endContours); tessData = _tessTool.TessAsTriVertexArray(flattenPoints, endContours, out int vertexCount); processGlyph = new ProcessedGlyph(tessData, (ushort)vertexCount); _glyphMeshCollection.RegisterCachedGlyph(glyphPlan.glyphIndex, processGlyph); } outputTextRun.AddGlyph( new GlyphRun(glyphPlan, processGlyph.tessData, processGlyph.vertextCount)); } }
void RenderAndShowMeasureBox() { bool flipY = chkFlipY.Checked; //set some Gdi+ props... g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(Color.White); Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface; Typography.OpenFont.TypefaceExtension2.UpdateAllCffGlyphBounds(typeface); float pxscale = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints); int lineSpacing = (int)System.Math.Ceiling((double)typeface.CalculateLineSpacing(LineSpacingChoice.TypoMetric) * pxscale); if (flipY) { //credit: //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly } //-------------------------------- //textspan measurement sample //-------------------------------- _currentTextPrinter.HintTechnique = (HintTechnique)lstHintList.SelectedItem; _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem; _currentTextPrinter.UpdateGlyphLayoutSettings(); //render at specific pos float x_pos = 0, y_pos = lineSpacing * 2; char[] textBuffer = txtInputChar.Text.ToCharArray(); //Example 1: this is a basic draw sample _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.TargetGraphics = g; _currentTextPrinter.DrawString( textBuffer, 0, textBuffer.Length, x_pos, y_pos ); // //-------------------------------------------------- //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw) //you can create you own class to hold userGlyphPlans.*** //2.1 _reusableUnscaledGlyphPlanList.Clear(); _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList); //2.2 //and we can print the formatted glyph plan later. y_pos -= lineSpacing;//next line _currentTextPrinter.FillColor = Color.Red; _currentTextPrinter.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x_pos, y_pos ); //Example 3: MeasureString UnscaledGlyphPlanList glyphPlans = new UnscaledGlyphPlanList(); _currentTextPrinter.GlyphLayoutMan.GenerateUnscaledGlyphPlans(glyphPlans); MeasuredStringBox strBox = _currentTextPrinter.GlyphLayoutMan.LayoutAndMeasureString( textBuffer, 0, textBuffer.Length, _currentTextPrinter.FontSizeInPoints); int j = glyphPlans.Count; float backup_xpos = x_pos; for (int i = 0; i < j; ++i) { UnscaledGlyphPlan glyphPlan = glyphPlans[i]; Typography.OpenFont.Glyph glyph = typeface.GetGlyphByIndex(glyphPlan.glyphIndex); // Typography.OpenFont.Bounds b = glyph.Bounds; // float xmin = b.XMin * pxscale; float ymin = b.YMin * pxscale; // float xmax = b.XMax * pxscale; float ymax = b.YMax * pxscale; // float glyph_x = x_pos + glyphPlan.OffsetX; g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin); x_pos += glyphPlan.AdvanceX * pxscale; } x_pos = backup_xpos; g.FillRectangle(Brushes.Red, new RectangleF(0, 0, 5, 5));//reference point(0,0) g.FillRectangle(Brushes.Green, new RectangleF(x_pos, y_pos, 3, 3)); float x_pos2 = x_pos + strBox.width + 10; g.DrawRectangle(Pens.Black, x_pos, y_pos + strBox.DescendingInPx, strBox.width, strBox.ClipHeightInPx); g.DrawRectangle(Pens.Red, x_pos, y_pos + strBox.DescendingInPx, strBox.width, strBox.LineSpaceInPx); g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos); //baseline g.DrawLine(Pens.Green, x_pos, y_pos + strBox.DescendingInPx, x_pos2, y_pos + strBox.DescendingInPx); //descending g.DrawLine(Pens.Magenta, x_pos, y_pos + strBox.AscendingInPx, x_pos2, y_pos + strBox.AscendingInPx); //ascending ////------------ ////draw another line (for reference) y_pos -= lineSpacing;//next line _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x_pos, y_pos ); //transform back if (flipY) { g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly } //--------- //txtMsgInfo.Text = "choice:" + choice.ToString() + "=" + lineSpacing.ToString(); }
void RenderAndShowMeasureBox() { bool flipY = chkFlipY.Checked; //set some Gdi+ props... _g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; _g.Clear(Color.White); Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface; Typography.OpenFont.Extensions.TypefaceExtensions.UpdateAllCffGlyphBounds(typeface); float pxscale = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints); int lineSpacing = (int)System.Math.Ceiling((double)typeface.CalculateLineSpacing(LineSpacingChoice.TypoMetric) * pxscale); if (flipY) { //credit: //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control _g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis _g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly } //-------------------------------- //textspan measurement sample //-------------------------------- _currentTextPrinter.HintTechnique = (HintTechnique)lstHintList.SelectedItem; _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem; _currentTextPrinter.UpdateGlyphLayoutSettings(); //render at specific pos float x_pos = 0, y_pos = lineSpacing * 2; char[] textBuffer = txtInputChar.Text.ToCharArray(); //Example 1: this is a basic draw sample _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.TargetGraphics = _g; //_currentTextPrinter.DrawString( // textBuffer, // 0, // textBuffer.Length, // x_pos, // y_pos // ); // //-------------------------------------------------- //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw) //you can create you own class to hold userGlyphPlans.*** //2.1 if (chkEnableMultiTypefaces.Checked) { _ftmGlyphPlansList.Clear(); _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, _ftmGlyphPlansList); //2.2 //and we can print the formatted glyph plan later. y_pos -= lineSpacing;//next line _currentTextPrinter.FillColor = Color.Red; _currentTextPrinter.DrawFromFormattedGlyphPlans( _ftmGlyphPlansList, x_pos, y_pos ); //-------------------------------------------------- //Example 3: MeasureString //3.1 use data in formatted_glyph_plan_list to measure string => OK, OR //3.2 use another 'light-weight' text printer to measure string (without drawing actual string) //3.1 _currentTextPrinter.MeasureGlyphPlanList(_ftmGlyphPlansList, out int measureWidth); _g.DrawRectangle(Pens.Red, x_pos, y_pos, measureWidth, 30); float baseline = y_pos; //3.2 draw each glyph bounds { int m = _ftmGlyphPlansList.Count; for (int i = 0; i < m; ++i) { FormattedGlyphPlanSeq seq = _ftmGlyphPlansList[i]; ResolvedFont resolvedFont = seq.ResolvedFont; Typeface localTypeface = resolvedFont.Typeface; pxscale = resolvedFont.GetScaleToPixelFromPointInSize(); GlyphPlanSequence glyph_seq = seq.Seq; var snapToPxScale = new GlyphPlanSequenceSnapPixelScaleLayout(seq.Seq, 0, glyph_seq.Count, pxscale); x_pos += (resolvedFont.WhitespaceWidth * seq.PrefixWhitespaceCount); int nn = 0;/// while (snapToPxScale.Read()) { //float cx = (float)Math.Round(snapToPxScale.ExactX + x_pos); //float cy = (float)Math.Floor(snapToPxScale.ExactY + baseline); UnscaledGlyphPlan glyphPlan = glyph_seq[nn]; Glyph glyph = localTypeface.GetGlyph(glyphPlan.glyphIndex); Bounds b = glyph.Bounds; // float xmin = b.XMin * pxscale; float ymin = b.YMin * pxscale; // float xmax = b.XMax * pxscale; float ymax = b.YMax * pxscale; // float glyph_x = x_pos + (glyphPlan.OffsetX * pxscale); _g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin); x_pos += glyphPlan.AdvanceX * pxscale; nn++; } x_pos += (resolvedFont.WhitespaceWidth * seq.PostfixWhitespaceCount); } } _ftmGlyphPlansList.Clear(); } else { _reusableUnscaledGlyphPlanList.Clear(); _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList); //2.2 //and we can print the formatted glyph plan later. y_pos -= lineSpacing;//next line _currentTextPrinter.FillColor = Color.Red; // GlyphPlanSequence seq = new GlyphPlanSequence(_reusableUnscaledGlyphPlanList); _currentTextPrinter.DrawFromGlyphPlans( seq, x_pos, y_pos ); //-------------------------------------------------- //Example 3: MeasureString float descending_px = _currentTextPrinter.FontDescedingPx; float ascending_px = _currentTextPrinter.FontAscendingPx; float lineSpacing_px = _currentTextPrinter.FontLineSpacingPx; float clippedHeight_px = _currentTextPrinter.FontClipHeightPx; _currentTextPrinter.MeasureGlyphPlanSeq(seq, out int textspanW); UnscaledGlyphPlanList glyphPlans = new UnscaledGlyphPlanList(); _currentTextPrinter.GenerateGlyphPlans(textBuffer, 0, textBuffer.Length, glyphPlans); int j = glyphPlans.Count; float backup_xpos = x_pos; for (int i = 0; i < j; ++i) { UnscaledGlyphPlan glyphPlan = glyphPlans[i]; Glyph glyph = typeface.GetGlyph(glyphPlan.glyphIndex); // Bounds b = glyph.Bounds; // float xmin = b.XMin * pxscale; float ymin = b.YMin * pxscale; // float xmax = b.XMax * pxscale; float ymax = b.YMax * pxscale; // float glyph_x = x_pos + (glyphPlan.OffsetX * pxscale); _g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin); x_pos += glyphPlan.AdvanceX * pxscale; } x_pos = backup_xpos; _g.FillRectangle(Brushes.Red, new RectangleF(0, 0, 5, 5));//reference point(0,0) _g.FillRectangle(Brushes.Green, new RectangleF(x_pos, y_pos, 3, 3)); float x_pos2 = x_pos + textspanW + 10; _g.DrawRectangle(Pens.Black, x_pos, y_pos + descending_px, textspanW, clippedHeight_px); _g.DrawRectangle(Pens.Red, x_pos, y_pos + descending_px, textspanW, lineSpacing_px); _g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos); //baseline _g.DrawLine(Pens.Green, x_pos, y_pos + descending_px, x_pos2, y_pos + descending_px); //descending _g.DrawLine(Pens.Magenta, x_pos, y_pos + ascending_px, x_pos2, y_pos + ascending_px); //ascending ////------------ ////draw another line (for reference) y_pos -= lineSpacing;//next line _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x_pos, y_pos ); } //transform back if (flipY) { _g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis _g.TranslateTransform(0.0F, -500); // Translate the drawing area accordingly } //--------- //txtMsgInfo.Text = "choice:" + choice.ToString() + "=" + lineSpacing.ToString(); }
private void cmdMeasureTextSpan_Click(object sender, System.EventArgs e) { //set some Gdi+ props... g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(Color.White); //credit: //http://stackoverflow.com/questions/1485745/flip-coordinates-when-drawing-to-control g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly //-------------------------------- //textspan measurement sample //-------------------------------- _currentTextPrinter.HintTechnique = (HintTechnique)lstHintList.SelectedItem; _currentTextPrinter.PositionTechnique = (PositionTechnique)cmbPositionTech.SelectedItem; //render at specific pos float x_pos = 0, y_pos = 100; char[] textBuffer = txtInputChar.Text.ToCharArray(); //Example 1: this is a basic draw sample _currentTextPrinter.FillColor = Color.Black; _currentTextPrinter.TargetGraphics = g; _currentTextPrinter.DrawString( textBuffer, 0, textBuffer.Length, x_pos, y_pos ); // //-------------------------------------------------- //Example 2: print glyph plan to 'user' list-> then draw it (or hold it/ not draw) //you can create you own class to hold userGlyphPlans.*** //2.1 _reusableUnscaledGlyphPlanList.Clear(); _currentTextPrinter.GenerateGlyphPlan(textBuffer, 0, textBuffer.Length, _reusableUnscaledGlyphPlanList); //2.2 //and we can print the formatted glyph plan later. y_pos -= _currentTextPrinter.FontLineSpacingPx; _currentTextPrinter.FillColor = Color.Red; _currentTextPrinter.DrawFromGlyphPlans( new GlyphPlanSequence(_reusableUnscaledGlyphPlanList), x_pos, y_pos ); //Example 3: MeasureString Typography.OpenFont.Typeface typeface = _currentTextPrinter.Typeface; UnscaledGlyphPlanList userGlyphPlans = new UnscaledGlyphPlanList(); _currentTextPrinter.GlyphLayoutMan.GenerateUnscaledGlyphPlans(userGlyphPlans); MeasuredStringBox strBox = new MeasuredStringBox(); throw new System.NotSupportedException(); //_currentTextPrinter.GlyphLayoutMan.LayoutAndMeasureString( // textBuffer, 0, textBuffer.Length, // _currentTextPrinter.FontSizeInPoints, // true, // userGlyphPlans); float x_pos2 = x_pos + strBox.width + 10; g.DrawRectangle(Pens.Red, x_pos, y_pos + strBox.descending, strBox.width, strBox.CalculateLineHeight()); g.DrawLine(Pens.Blue, x_pos, y_pos, x_pos2, y_pos); //baseline g.DrawLine(Pens.Green, x_pos, y_pos + strBox.descending, x_pos2, y_pos + strBox.descending); //descending g.DrawLine(Pens.Magenta, x_pos, y_pos + strBox.ascending, x_pos2, y_pos + strBox.ascending); //ascending Typography.OpenFont.TypefaceExtension2.UpdateAllCffGlyphBounds(typeface); float pxscale = typeface.CalculateScaleToPixelFromPointSize(_currentTextPrinter.FontSizeInPoints); int j = userGlyphPlans.Count; for (int i = 0; i < j; ++i) { UnscaledGlyphPlan glyphPlan = userGlyphPlans[i]; Typography.OpenFont.Glyph glyph = typeface.GetGlyphByIndex(glyphPlan.glyphIndex); // Typography.OpenFont.Bounds b = glyph.Bounds; // float xmin = b.XMin * pxscale; float ymin = b.YMin * pxscale; // float xmax = b.XMax * pxscale; float ymax = b.YMax * pxscale; // float glyph_x = x_pos + glyphPlan.OffsetX; g.DrawRectangle(Pens.Red, glyph_x + xmin, y_pos + ymin, xmax - xmin, ymax - ymin); } //------------ _currentTextPrinter.FillColor = Color.Black; //transform back g.ScaleTransform(1.0F, -1.0F); // Flip the Y-Axis g.TranslateTransform(0.0F, -(float)300); // Translate the drawing area accordingly }