public void DrawString(RenderVxFormattedString renderVx, double x, double y) { //TODO: review here float ox = _painter.OriginX; float oy = _painter.OriginY; //1. update some props.. //2. update current type face UpdateGlyphLayoutSettings(); _glyphMeshStore.SetFont(_currentTypeface, this.FontSizeInPoints); _glyphMeshStore.SimulateOblique = this.SimulateSlant; //3. layout glyphs with selected layout technique //TODO: review this again, we should use pixel? float fontSizePoint = this.FontSizeInPoints; float scale = _currentTypeface.CalculateScaleToPixelFromPointSize(fontSizePoint); RenderVxGlyphPlan[] glyphPlans = renderVx.GlyphList; int j = glyphPlans.Length; //--------------------------------------------------- //consider use cached glyph, to increase performance //GlyphPosPixelSnapKind x_snap = this.GlyphPosPixelSnapX; //GlyphPosPixelSnapKind y_snap = this.GlyphPosPixelSnapY; float g_x = 0; float g_y = 0; float baseY = (int)y; for (int i = 0; i < j; ++i) { RenderVxGlyphPlan glyphPlan = glyphPlans[i]; //----------------------------------- //TODO: review here *** //PERFORMANCE revisit here //if we have create a vxs we can cache it for later use? //----------------------------------- VertexStore vxs = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex); g_x = (float)(glyphPlan.x * scale + x); g_y = (float)glyphPlan.y * scale; _painter.SetOrigin(g_x, g_y); _painter.Fill(vxs); } //restore prev origin _painter.SetOrigin(ox, oy); }
protected override void SetGlyphVxs(GlyphBox glyphBox, Typeface typeface, float sizeInPoint) { if (glyphBox is VxsGlyphBox vxsGlyphBox) { _glyphMeshStore.SetFont(typeface, sizeInPoint);//20= font size _glyphMeshStore.FlipGlyphUpward = true; if (glyphBox.IsItalic) { _glyphMeshStore.SimulateOblique = glyphBox.IsItalic; } vxsGlyphBox.GlyphVxs = _glyphMeshStore.GetGlyphMesh(glyphBox.GlyphIndex); if (_glyphMeshStore.SimulateOblique) { _glyphMeshStore.SimulateOblique = false; } } }
private void button3_Click(object sender, EventArgs e) { //it should be faster if we use 'mesh' cache //instead of read-transform it every time like code above(button2_click) LoadFont(); float font_size_in_Point = 20; _glyphMeshStore.SetFont(_latinModernMathFont, font_size_in_Point);//20= font size _glyphMeshStore.FlipGlyphUpward = true; float px_scale = _latinModernMathFont.CalculateScaleToPixelFromPointSize(font_size_in_Point); using (Tools.BorrowAggPainter(_memBmp, out var p)) { p.Clear(PixelFarm.Drawing.Color.White); float prevX = p.OriginX; float prevY = p.OriginY; int line_left = 10; int line_top = 50; p.SetOrigin(line_left, line_top);//*** test //draw reference point p.FillRect(0, 0, 5, 5, PixelFarm.Drawing.Color.Red); char[] test_str = "‽_x‾".ToCharArray(); int inline_left = 0; int inline_top = 0; //---------- GlyphLayout glyphLayout = new GlyphLayout(); glyphLayout.ScriptLang = new ScriptLang("math"); glyphLayout.Typeface = _latinModernMathFont; //temp fix for some typeface glyphLayout.SetGlyphIndexNotFoundHandler((glyph_layout, codepoint, next_codepoint) => { switch (codepoint) { //overline unicode case 8254: return(2246); //overline-combine, this will break into 3 parts in math layout process } return(0); }); // glyphLayout.Layout(test_str, 0, test_str.Length); List <UnscaledGlyphPlan> glyphPlans = new List <UnscaledGlyphPlan>(); foreach (UnscaledGlyphPlan glypyPlan in glyphLayout.GetUnscaledGlyphPlanIter()) { glyphPlans.Add(glypyPlan); } //-------- for (int i = 0; i < glyphPlans.Count; ++i) { //ushort glyphIndex = _latinModernMathFont.GetGlyphIndex((int)test_str[i]); ////do some glyph-substitution //ushort advW = _latinModernMathFont.GetAdvanceWidth((int)test_str[i]);//unscale glyph width //now scale it to specific font size UnscaledGlyphPlan glyphPlan = glyphPlans[i]; int advW_s = (int)System.Math.Round(px_scale * glyphPlan.AdvanceX); VertexStore v1 = _glyphMeshStore.GetGlyphMesh(glyphPlan.glyphIndex); p.SetOrigin(line_left + inline_left, line_top + inline_top); p.Fill(v1, PixelFarm.Drawing.Color.Black); inline_left += advW_s;//move } //restore p.SetOrigin(prevX, prevY); } //----------- CopyBitmapToScreen(); }
GlyphBitmap GetGlyphBitmapFromColorOutlineGlyph(ushort glyphIndex, GlyphMeshStore glyphMeshStore, ushort colorLayerStart) { //not found=> create a newone Typography.OpenFont.Tables.COLR _colrTable = _typeface.COLRTable; Typography.OpenFont.Tables.CPAL _cpalTable = _typeface.CPALTable; Q1RectD totalBounds = Q1RectD.ZeroIntersection(); { //calculate bounds of this glyph ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { BoundingRect.GetBoundingRect(glyphMeshStore.GetGlyphMesh(_colrTable.GlyphLayers[c]), ref totalBounds); } } //dbugExportCount++; var memBmp = new MemBitmap((int)Math.Round(totalBounds.Width), (int)Math.Round(totalBounds.Height));//??? int offset_x = 0; int offset_y = 0; using (Tools.BorrowAggPainter(memBmp, out AggPainter painter)) { painter.Clear(Color.Transparent); painter.SetOrigin(0, 0); offset_x = -(int)(totalBounds.Left); offset_y = -(int)(totalBounds.Bottom); ushort colorLayerCount = _colrTable.LayerCounts[glyphIndex]; int palette = 0; // FIXME: assume palette 0 for now for (int c = colorLayerStart; c < colorLayerStart + colorLayerCount; ++c) { _cpalTable.GetColor( _cpalTable.Palettes[palette] + _colrTable.GlyphPalettes[c], //index out byte r, out byte g, out byte b, out byte a); ushort gIndex = _colrTable.GlyphLayers[c]; VertexStore vxs = glyphMeshStore.GetGlyphMesh(gIndex); using (Tools.BorrowVxs(out var v1)) { vxs.TranslateToNewVxs(offset_x, offset_y, v1); painter.FillColor = new Color(r, g, b);//? a component painter.Fill(v1); } } //find ex #if DEBUG //memBmp.SaveImage("a0x" + (dbugExportCount) + ".png"); #endif } return(new GlyphBitmap { Bitmap = memBmp, Width = memBmp.Width, Height = memBmp.Height, ImageStartX = -offset_x, //offset back ImageStartY = -offset_y //offset back }); }