public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] clusterMapIndices, uint startingTextPosition, CanvasGlyphOrientation glyphOrientation) { if (glyphs == null || glyphs.Length == 0) { return; } float scaledFontAscent = fontFace.Ascent * fontSize; float subscriptBaselineDropAmount = scaledFontAscent * subscriptBaselineScale; float superscriptBaselineRaiseAmount = scaledFontAscent * superscriptBaselineScale; // Draw glyph-by-glyph. for (int i = 0; i < glyphs.Length; ++i) { CanvasGlyph[] singleGlyph = new CanvasGlyph[1]; singleGlyph[0] = glyphs[i]; Vector2 positionForThisGlyph = position; CustomBrushData brushData = (CustomBrushData)brush; if (brushData != null) { if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Lower) { positionForThisGlyph.Y += subscriptBaselineDropAmount; } else if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Raise) { positionForThisGlyph.Y -= superscriptBaselineRaiseAmount; } } DrawingSession.DrawGlyphRun( positionForThisGlyph, fontFace, fontSize, singleGlyph, isSideways, bidiLevel, TextBrush); position.X += glyphs[i].Advance; } }
void SplitJustifiedGlyphsIntoRuns(CanvasTextAnalyzer textAnalyzer, LayoutBox layoutBox, CanvasGlyph[] justifiedGlyphs, bool needsAdditionalJustificationCharacters) { int glyphIndex = 0; float xPosition = (float)layoutBox.Rectangle.Right; for (int i = 0; i < layoutBox.GlyphRuns.Count; i++) { if (layoutBox.GlyphRuns[i].Glyphs.Count == 0) { continue; } int originalGlyphCountForThisRun = layoutBox.GlyphRuns[i].Glyphs.Count; if (needsAdditionalJustificationCharacters) { // Replace the glyph data, since justification can modify glyphs CanvasGlyph[] justifiedGlyphsForThisGlyphRun = new CanvasGlyph[layoutBox.GlyphRuns[i].Glyphs.Count]; for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; j++) { justifiedGlyphsForThisGlyphRun[j] = justifiedGlyphs[glyphIndex + j]; } CanvasCharacterRange range = layoutBox.GlyphRuns[i].GetRange(); var glyphRunClusterMap = layoutBox.GlyphRuns[i].GetClusterMap(range); var glyphRunShaping = layoutBox.GlyphRuns[i].GetShaping(); CanvasGlyph[] newSetOfGlyphs = textAnalyzer.AddGlyphsAfterJustification( layoutBox.GlyphRuns[i].FormattingSpan.FontFace, layoutBox.GlyphRuns[i].FormattingSpan.FontSize, layoutBox.GlyphRuns[i].FormattingSpan.Script, glyphRunClusterMap, layoutBox.GlyphRuns[i].Glyphs.ToArray(), justifiedGlyphsForThisGlyphRun, glyphRunShaping); layoutBox.GlyphRuns[i].Glyphs = new List <CanvasGlyph>(newSetOfGlyphs); } else { for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; j++) { layoutBox.GlyphRuns[i].Glyphs[j] = justifiedGlyphs[glyphIndex + j]; } } glyphIndex += originalGlyphCountForThisRun; } }
public void LoadPage(Page page) { MainGlyph = new CanvasGlyph(WordConfig) { Redactor = _redactor, ParentVectorRedactor = this }; foreach (var line in page.Lines) { var lineGlyph = MainGlyph.InsertNewLineGlyph(line); foreach (var word in line.Words) { lineGlyph.InsertNewWordGlyph(word); } } }
public VectorRedactorRepository(Graphics canvas, Redactor redactor, VectorRedactorConfig config) { Canvas = canvas; _redactor = redactor; canvas.SmoothingMode = SmoothingMode.HighQuality; Layout = new Layout(canvas); WordConfig = new GlyphConfig(config.WordBrush, config.WordPen); LineConfig = new GlyphConfig(config.LineBrush, config.LinePen); RedactorState = RedactorStates.Default; MainGlyph = new CanvasGlyph(WordConfig) { Redactor = _redactor, ParentVectorRedactor = this }; MainGlyph.MainGlyph = MainGlyph; ActiveGlyph = MainGlyph; }
CanvasJustificationOpportunity[] GetJustificationOpportunities(CanvasTextAnalyzer textAnalyzer, LayoutBox layoutBox, out CanvasGlyph[] allGlyphs) { int layoutBoxGlyphCount = layoutBox.GetGlyphCount(); CanvasJustificationOpportunity[] justificationOpportunities = new CanvasJustificationOpportunity[layoutBoxGlyphCount]; allGlyphs = new CanvasGlyph[layoutBoxGlyphCount]; int glyphIndex = 0; for (int i = 0; i < layoutBox.GlyphRuns.Count; i++) { if (layoutBox.GlyphRuns[i].Glyphs.Count == 0) { continue; } CanvasCharacterRange range = layoutBox.GlyphRuns[i].GetRange(); var glyphRunClusterMap = layoutBox.GlyphRuns[i].GetClusterMap(range); var glyphRunShaping = layoutBox.GlyphRuns[i].GetShaping(); var justificationOpportunitiesThisGlyphRun = textAnalyzer.GetJustificationOpportunities( range, layoutBox.GlyphRuns[i].FormattingSpan.FontFace, layoutBox.GlyphRuns[i].FormattingSpan.FontSize, layoutBox.GlyphRuns[i].FormattingSpan.Script, glyphRunClusterMap, glyphRunShaping); for (int j = 0; j < layoutBox.GlyphRuns[i].Glyphs.Count; ++j) { justificationOpportunities[glyphIndex + j] = justificationOpportunitiesThisGlyphRun[j]; allGlyphs[glyphIndex + j] = layoutBox.GlyphRuns[i].Glyphs[j]; } glyphIndex += layoutBox.GlyphRuns[i].Glyphs.Count; } return(justificationOpportunities); }
CanvasJustificationOpportunity[] GetJustificationOpportunities(CanvasTextAnalyzer textAnalyzer, int startingGlyphRunIndex, int endingGlyphRunIndex, int glyphCount, out CanvasGlyph[] allGlyphs) { CanvasJustificationOpportunity[] justificationOpportunities = new CanvasJustificationOpportunity[glyphCount]; allGlyphs = new CanvasGlyph[glyphCount]; int glyphIndex = 0; for (int i = startingGlyphRunIndex; i < endingGlyphRunIndex; ++i) { if (glyphRuns[i].Glyphs.Count == 0) { continue; } CanvasCharacterRange range = glyphRuns[i].GetRange(); var glyphRunClusterMap = glyphRuns[i].GetClusterMap(range); var glyphRunShaping = glyphRuns[i].GetShaping(); var justificationOpportunitiesThisGlyphRun = textAnalyzer.GetJustificationOpportunities( range, glyphRuns[i].FormattingSpan.FontFace, glyphRuns[i].FormattingSpan.FontSize, glyphRuns[i].FormattingSpan.Script, glyphRunClusterMap, glyphRunShaping); for (int j = 0; j < glyphRuns[i].Glyphs.Count; ++j) { justificationOpportunities[glyphIndex + j] = justificationOpportunitiesThisGlyphRun[j]; allGlyphs[glyphIndex + j] = glyphRuns[i].Glyphs[j]; } glyphIndex += glyphRuns[i].Glyphs.Count; } return(justificationOpportunities); }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] clusterMapIndices, uint textPosition, CanvasGlyphOrientation glyphOrientation) { var script = GetScript(textPosition); if (CurrentMode == Mode.BuildTypographyList) { CanvasTypographyFeatureName[] features = fontFace.GetSupportedTypographicFeatureNames(script); foreach (var featureName in features) { TypographyFeatureInfo featureInfo = new TypographyFeatureInfo(featureName); if (!TypographyOptions.Contains(featureInfo)) { TypographyOptions.Add(featureInfo); } } } else { if (glyphs == null || glyphs.Length == 0) { return; } // // This demo handles only simple Latin text with no diacritical // markers or ligatures, so we can make assumptions about the // mapping of text positions to glyph indices. This works fine for // the sake of this example. // // In general, apps should use the cluster map to map text // positions to glyphs while knowing that glyph substitution can happen // for reasons besides typography. // uint[] codePoints = new uint[glyphs.Length]; for (int i = 0; i < glyphs.Length; i++) { int glyphTextPosition = 0; for (int j = 0; j < clusterMapIndices.Length; j++) { if (clusterMapIndices[j] == i) { glyphTextPosition = j; break; } } codePoints[i] = textString[glyphTextPosition]; } int[] nominalGlyphIndices = fontFace.GetGlyphIndices(codePoints); CanvasGlyph[] unsubstitutedGlyphs = new CanvasGlyph[glyphs.Length]; for (int i = 0; i < glyphs.Length; i++) { unsubstitutedGlyphs[i] = glyphs[i]; unsubstitutedGlyphs[i].Index = nominalGlyphIndices[i]; } bool[] eligible = fontFace.GetTypographicFeatureGlyphSupport(script, FeatureToHighlight, unsubstitutedGlyphs); var highlightBrush = new CanvasSolidColorBrush(currentDrawingSession, Colors.Yellow); for (int i = 0; i < glyphs.Length; ++i) { if (eligible[i]) { CanvasGlyph[] singleGlyph = new CanvasGlyph[1]; singleGlyph[0] = glyphs[i]; currentDrawingSession.DrawGlyphRun( position, fontFace, fontSize, singleGlyph, isSideways, bidiLevel, highlightBrush); } position.X += glyphs[i].Advance; } } }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] custerMapIndices, uint textPosition, CanvasGlyphOrientation glyphOrientation) { Metrics m = new Metrics(); m.Ascent = fontFace.Ascent; m.LineGap = fontFace.LineGap; m.Descent = fontFace.Descent; m.CapHeight = fontFace.CapHeight; m.LowercaseLetterHeight = fontFace.LowercaseLetterHeight; m.Bounds = fontFace.GetGlyphRunBounds( drawingSession, position, fontSize, glyphs, isSideways, bidiLevel); GlyphRunMetrics.Add(m); }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] custerMapIndices, uint textPosition, CanvasGlyphOrientation glyphOrientation) { if (glyphs == null) return; var previousTransform = drawingSession.Transform; drawingSession.Transform = CanvasTextLayout.GetGlyphOrientationTransform(glyphOrientation, isSideways, position); drawingSession.DrawGlyphRun( position, fontFace, fontSize, glyphs, isSideways, bidiLevel, textBrush); drawingSession.Transform = previousTransform; }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] clusterMapIndices, uint startingTextPosition, CanvasGlyphOrientation glyphOrientation) { if (glyphs == null || glyphs.Length == 0) return; float scaledFontAscent = fontFace.Ascent * fontSize; float subscriptBaselineDropAmount = scaledFontAscent * subscriptBaselineScale; float superscriptBaselineRaiseAmount = scaledFontAscent * superscriptBaselineScale; // Draw glyph-by-glyph. for (int i = 0; i < glyphs.Length; ++i) { CanvasGlyph[] singleGlyph = new CanvasGlyph[1]; singleGlyph[0] = glyphs[i]; Vector2 positionForThisGlyph = position; CustomBrushData brushData = (CustomBrushData)brush; if (brushData != null) { if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Lower) { positionForThisGlyph.Y += subscriptBaselineDropAmount; } else if (brushData.BaselineAdjustment == CustomBrushData.BaselineAdjustmentType.Raise) { positionForThisGlyph.Y -= superscriptBaselineRaiseAmount; } } DrawingSession.DrawGlyphRun( positionForThisGlyph, fontFace, fontSize, singleGlyph, isSideways, bidiLevel, TextBrush); position.X += glyphs[i].Advance; } }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] custerMapIndices, uint textPosition, CanvasGlyphOrientation glyphOrientation) { CanvasGeometry geometry = CanvasGeometry.CreateGlyphRun( resourceCreator, position, fontFace, fontSize, glyphs, isSideways, bidiLevel, measuringMode, glyphOrientation); geometries.Add(geometry); }
void SplitJustifiedGlyphsIntoRuns(CanvasTextAnalyzer textAnalyzer, int startingGlyphRunIndex, int endingGlyphRunIndex, CanvasGlyph[] justifiedGlyphs, bool needsAdditionalJustificationCharacters) { int glyphIndex = 0; float xPosition = glyphRuns[startingGlyphRunIndex].Position.X; for (int i = startingGlyphRunIndex; i < endingGlyphRunIndex; ++i) { if (glyphRuns[i].Glyphs.Count == 0) { continue; } // Adjust glyph run positioning based on justification glyphRuns[i].Position = new Vector2() { X = xPosition, Y = glyphRuns[i].Position.Y }; // Update running total glyph run advance for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++) { xPosition += glyphRuns[i].Glyphs[j].Advance; } if (needsAdditionalJustificationCharacters) { // Replace the glyph data, since justification can modify glyphs CanvasGlyph[] justifiedGlyphsForThisGlyphRun = new CanvasGlyph[glyphRuns[i].Glyphs.Count]; for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++) { justifiedGlyphsForThisGlyphRun[j] = justifiedGlyphs[glyphIndex + j]; } CanvasCharacterRange range = glyphRuns[i].GetRange(); var glyphRunClusterMap = glyphRuns[i].GetClusterMap(range); var glyphRunShaping = glyphRuns[i].GetShaping(); CanvasGlyph[] newSetOfGlyphs = textAnalyzer.AddGlyphsAfterJustification( glyphRuns[i].FormattingSpan.FontFace, glyphRuns[i].FormattingSpan.FontSize, glyphRuns[i].FormattingSpan.Script, glyphRunClusterMap, glyphRuns[i].Glyphs.ToArray(), justifiedGlyphsForThisGlyphRun, glyphRunShaping); glyphRuns[i].Glyphs = new List <CanvasGlyph>(newSetOfGlyphs); } else { for (int j = 0; j < glyphRuns[i].Glyphs.Count; j++) { glyphRuns[i].Glyphs[j] = justifiedGlyphs[glyphIndex + j]; } } glyphIndex += glyphRuns[i].Glyphs.Count; } }
public void DrawGlyphRun( Vector2 position, CanvasFontFace fontFace, float fontSize, CanvasGlyph[] glyphs, bool isSideways, uint bidiLevel, object brush, CanvasTextMeasuringMode measuringMode, string locale, string textString, int[] clusterMapIndices, uint textPosition, CanvasGlyphOrientation glyphOrientation) { var script = GetScript(textPosition); if (CurrentMode == Mode.BuildTypographyList) { CanvasTypographyFeatureName[] features = fontFace.GetSupportedTypographicFeatureNames(script); foreach (var featureName in features) { TypographyFeatureInfo featureInfo = new TypographyFeatureInfo(featureName); if (!TypographyOptions.Contains(featureInfo)) { TypographyOptions.Add(featureInfo); } } } else { if (glyphs == null || glyphs.Length == 0) return; // // This demo handles only simple Latin text with no diacritical // markers or ligatures, so we can make assumptions about the // mapping of text positions to glyph indices. This works fine for // the sake of this example. // // In general, apps should use the cluster map to map text // positions to glyphs while knowing that glyph substitution can happen // for reasons besides typography. // uint[] codePoints = new uint[glyphs.Length]; for (int i = 0; i < glyphs.Length; i++) { int glyphTextPosition = 0; for (int j=0; j<clusterMapIndices.Length; j++) { if (clusterMapIndices[j] == i) { glyphTextPosition = j; break; } } codePoints[i] = textString[glyphTextPosition]; } int[] nominalGlyphIndices = fontFace.GetGlyphIndices(codePoints); CanvasGlyph[] unsubstitutedGlyphs = new CanvasGlyph[glyphs.Length]; for (int i = 0; i < glyphs.Length; i++) { unsubstitutedGlyphs[i] = glyphs[i]; unsubstitutedGlyphs[i].Index = nominalGlyphIndices[i]; } bool[] eligible = fontFace.GetTypographicFeatureGlyphSupport(script, FeatureToHighlight, unsubstitutedGlyphs); var highlightBrush = new CanvasSolidColorBrush(currentDrawingSession, Colors.Yellow); for (int i = 0; i < glyphs.Length; ++i) { if (eligible[i]) { CanvasGlyph[] singleGlyph = new CanvasGlyph[1]; singleGlyph[0] = glyphs[i]; currentDrawingSession.DrawGlyphRun( position, fontFace, fontSize, singleGlyph, isSideways, bidiLevel, highlightBrush); } position.X += glyphs[i].Advance; } } }