示例#1
0
        void LayoutWithoutHorizontalFitAlign(IGlyphPositions posStream, GlyphPlanList outputGlyphPlanList)
        {
            //the default OpenFont layout without fit-to-writing alignment
            int    finalGlyphCount = posStream.Count;
            float  pxscale         = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints);
            double cx = 0;
            short  cy = 0;

            for (int i = 0; i < finalGlyphCount; ++i)
            {
                short  offsetX, offsetY, advW; //all from pen-pos
                ushort glyphIndex = posStream.GetGlyph(i, out offsetX, out offsetY, out advW);

                float s_advW  = advW * pxscale;
                float exact_x = (float)(cx + offsetX * pxscale);
                float exact_y = (float)(cy + offsetY * pxscale);

                //outputGlyphPlanList.Append(new GlyphPlan(
                //   glyphIndex,
                //    exact_x,
                //    exact_y,
                //    advW)); //old?
                outputGlyphPlanList.Append(new GlyphPlan(
                                               glyphIndex,
                                               exact_x,
                                               exact_y,
                                               s_advW));

                cx += s_advW;
            }
        }
示例#2
0
        /// <summary>
        /// always create new vxs for this glyph, no caching
        /// </summary>
        /// <param name="glyphIndex"></param>
        /// <returns></returns>
        public VertexStore GetNewUnFlattenVxs(ushort glyphIndex)
        {
            _currentGlyphBuilder.BuildFromGlyphIndex(glyphIndex, _currentFontSizeInPoints);
            DynamicOutline dynamicOutline = _currentGlyphBuilder.LatestGlyphFitOutline;

            //-----------------------------------
            _tovxs.Reset();
            float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_currentFontSizeInPoints);

            if (dynamicOutline != null)
            {
                //TODO: review dynamic outline
                dynamicOutline.GenerateOutput(new ContourToGlyphTranslator(_tovxs), pxscale);
                //version 3
                using (Tools.BorrowVxs(out var v1))
                {
                    _tovxs.WriteUnFlattenOutput(v1, 1);
                    return(FlipGlyphUpward ? v1.CreateTrim(s_flipY) : v1.CreateTrim());
                }
            }
            else
            {
                using (Tools.BorrowVxs(out var v1))
                {
                    _currentGlyphBuilder.ReadShapes(_tovxs);
                    _tovxs.WriteUnFlattenOutput(v1, 1); //write to temp buffer first

                    //then
                    return(FlipGlyphUpward ? v1.CreateTrim(s_flipY) : v1.CreateTrim());
                }
            }
        }
示例#3
0
        /// <summary>
        /// get from cache or create a new one
        /// </summary>
        /// <param name="reqFont"></param>
        /// <returns></returns>
        public SimpleFontAtlas GetFontAtlas(RequestFont reqFont,
                                            out GLBitmap glBmp)
        {
            int             fontKey = reqFont.FontKey;
            SimpleFontAtlas fontAtlas;

            if (!_createdAtlases.TryGetValue(fontKey, out fontAtlas))
            {
                Typeface resolvedTypeface = textServices.ResolveTypeface(reqFont);
                //if we don't have
                //the create it
                SimpleFontAtlasBuilder atlasBuilder = null;
                var textureGen = new GlyphTextureBitmapGenerator();
                textureGen.CreateTextureFontFromScriptLangs(
                    resolvedTypeface,
                    reqFont.SizeInPoints,
                    _textureKind,
                    _currentScriptLangs,
                    (glyphIndex, glyphImage, outputAtlasBuilder) =>
                {
                    if (outputAtlasBuilder != null)
                    {
                        //finish
                        atlasBuilder = outputAtlasBuilder;
                    }
                }
                    );

                GlyphImage totalGlyphsImg = atlasBuilder.BuildSingleImage();
                //create atlas
                fontAtlas            = atlasBuilder.CreateSimpleFontAtlas();
                fontAtlas.TotalGlyph = totalGlyphsImg;
#if DEBUG
                //save glyph image for debug
                //PixelFarm.Agg.ActualImage.SaveImgBufferToPngFile(
                //    totalGlyphsImg.GetImageBuffer(),
                //    totalGlyphsImg.Width * 4,
                //    totalGlyphsImg.Width, totalGlyphsImg.Height,
                //    "d:\\WImageTest\\total_" + reqFont.Name + "_" + reqFont.SizeInPoints + ".png");
#endif

                //cache the atlas
                _createdAtlases.Add(fontKey, fontAtlas);
                //
                //calculate some commonly used values
                fontAtlas.SetTextureScaleInfo(
                    resolvedTypeface.CalculateScaleToPixelFromPointSize(fontAtlas.OriginalFontSizePts),
                    resolvedTypeface.CalculateScaleToPixelFromPointSize(reqFont.SizeInPoints));
                //TODO: review here, use scaled or unscaled values
                fontAtlas.SetCommonFontMetricValues(
                    resolvedTypeface.Ascender,
                    resolvedTypeface.Descender,
                    resolvedTypeface.LineGap,
                    resolvedTypeface.CalculateRecommendLineSpacing());
            }

            glBmp = _loadedGlyphs.GetOrCreateNewOne(fontAtlas);
            return(fontAtlas);
        }
示例#4
0
 protected override void OnFontSizeChanged()
 {
     //update some font matrix property
     if (_currentTypeface != null)
     {
         float pointToPixelScale = _currentTypeface.CalculateScaleToPixelFromPointSize(this.FontSizeInPoints);
         this.FontAscendingPx   = _currentTypeface.Ascender * pointToPixelScale;
         this.FontDescedingPx   = _currentTypeface.Descender * pointToPixelScale;
         this.FontLineGapPx     = _currentTypeface.LineGap * pointToPixelScale;
         this.FontLineSpacingPx = FontAscendingPx - FontDescedingPx + FontLineGapPx;
     }
 }
示例#5
0
        /// <summary>
        /// get glyph mesh from current font setting
        /// </summary>
        /// <param name="glyphIndex"></param>
        /// <returns></returns>
        public VertexStore GetGlyphMesh(ushort glyphIndex)
        {
            GlyphMeshData glyphMeshData = InternalGetGlyphMesh(glyphIndex);

            if (glyphMeshData.vxsStore == null)
            {
                //build vxs
                _tovxs.Reset();
                float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_currentFontSizeInPoints);
                GlyphDynamicOutline dynamicOutline = glyphMeshData.dynamicOutline;
                if (dynamicOutline != null)
                {
                    dynamicOutline.GenerateOutput(_tovxs, pxscale);
                    glyphMeshData.vxsStore = new VertexStore();
                    _tovxs.WriteOutput(glyphMeshData.vxsStore, _vxsPool);
                }
                else
                {
                    //no dynamic outline
                    glyphMeshData.vxsStore = new VertexStore();
                    _currentGlyphBuilder.ReadShapes(_tovxs);
                    //TODO: review here,
                    //float pxScale = _glyphPathBuilder.GetPixelScale();
                    _tovxs.WriteOutput(glyphMeshData.vxsStore, _vxsPool);
                }
            }
            return(glyphMeshData.vxsStore);
        }
        /// <summary>
        /// get glyph mesh from current font setting
        /// </summary>
        /// <param name="glyphIndex"></param>
        /// <returns></returns>
        public VertexStore GetGlyphMesh(ushort glyphIndex)
        {
            GlyphMeshData glyphMeshData = InternalGetGlyphMesh(glyphIndex);

            if (glyphMeshData.vxsStore == null)
            {
                //build vxs
                _tovxs.Reset();
                float pxscale = _currentTypeface.CalculateScaleToPixelFromPointSize(_currentFontSizeInPoints);
                GlyphDynamicOutline dynamicOutline = glyphMeshData.dynamicOutline;
                if (dynamicOutline != null)
                {
                    dynamicOutline.GenerateOutput(_tovxs, pxscale);

                    //version 3
                    if (_flipGlyphUpward)
                    {
                        _vxs1.Clear(); //write to temp buffer first
                        _tovxs.WriteOutput(_vxs1);

                        VertexStore vxs = new VertexStore();
                        PixelFarm.Agg.VertexStoreTransformExtensions.TransformToVxs(_invertY, _vxs1, vxs);
                        //then
                        glyphMeshData.vxsStore = vxs;
                    }
                    else
                    {
                        glyphMeshData.vxsStore = new VertexStore();
                        _tovxs.WriteOutput(glyphMeshData.vxsStore);
                    }
                }
                else
                {
                    if (_flipGlyphUpward)
                    {
                        _vxs1.Clear(); //write to temp buffer first

                        _currentGlyphBuilder.ReadShapes(_tovxs);
                        _tovxs.WriteOutput(_vxs1);

                        VertexStore vxs = new VertexStore();
                        PixelFarm.Agg.VertexStoreTransformExtensions.TransformToVxs(_invertY, _vxs1, vxs);
                        //then
                        glyphMeshData.vxsStore = vxs;
                    }
                    else
                    {
                        //no dynamic outline

                        _currentGlyphBuilder.ReadShapes(_tovxs);
                        //TODO: review here,
                        //float pxScale = _glyphPathBuilder.GetPixelScale();

                        glyphMeshData.vxsStore = new VertexStore();
                        _tovxs.WriteOutput(glyphMeshData.vxsStore);
                    }
                }
            }
            return(glyphMeshData.vxsStore);
        }
示例#7
0
        public static MeasuredStringBox LayoutAndMeasureString(
            this GlyphLayout glyphLayout,
            char[] textBuffer,
            int startAt,
            int len,
            float fontSizeInPoints,
            bool snapToGrid = true)
        {
            //1. unscale layout, in design unit
            glyphLayout.Layout(textBuffer, startAt, len);


            //2. scale  to specific font size

            Typeface typeface = glyphLayout.Typeface;
            float    pxscale  = typeface.CalculateScaleToPixelFromPointSize(fontSizeInPoints);

            //....
            GenerateScaledGlyphPlans(
                glyphLayout,
                pxscale,
                snapToGrid,
                out float scaled_accumX);

            return(new MeasuredStringBox(
                       scaled_accumX,
                       typeface.Ascender * pxscale,
                       typeface.Descender * pxscale,
                       typeface.LineGap * pxscale,
                       Typography.OpenFont.Extensions.TypefaceExtensions.CalculateRecommendLineSpacing(typeface) * pxscale));
        }
示例#8
0
        public static double GetAscent(string fontFamily, double fontSize)
        {
            Typeface typeFace = GetTypeFace(fontFamily);
            var      scale    = typeFace.CalculateScaleToPixelFromPointSize((float)fontSize);

            return(typeFace.Ascender * scale);
        }
示例#9
0
        public static double GetLineHeight(string fontFamily, double fontSize)
        {
            Typeface typeFace = GetTypeFace(fontFamily);
            var      scale    = typeFace.CalculateScaleToPixelFromPointSize((float)fontSize);

            return((typeFace.Ascender - typeFace.Descender + typeFace.LineGap) * scale);
        }
示例#10
0
        public static float GetScale(string fontFamily, double fontSize)
        {
            Typeface typeFace = GetTypeFace(fontFamily);
            var      scale    = typeFace.CalculateScaleToPixelFromPointSize((float)fontSize);

            return(scale);
        }
示例#11
0
        float ITextService.MeasureBlankLineHeight(RequestFont font)
        {
            Typeface typeface = ResolveTypeface(font);

            return((int)(Math.Round(typeface.CalculateMaxLineClipHeight() *
                                    typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints))));
        }
示例#12
0
        //
        public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan,
                                                     ILineSegmentList lineSegs,
                                                     RequestFont font,
                                                     int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight)
        {
            //layout
            //from font
            //resolve for typeface
            //
            Typeface typeface = ResolveTypeface(font);

            _txtServices.SetCurrentFont(typeface, font.SizeInPoints);


            MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs;
            float             scale      = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            outputTotalW = 0;
            int j   = mylineSegs.Count;
            int pos = 0; //start at 0

            _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer());

            for (int i = 0; i < j; ++i)
            {
                //get each segment
                MyLineSegment lineSeg = (MyLineSegment)mylineSegs.GetSegment(i);
                //each line seg may has different script lang
                _txtServices.CurrentScriptLang = lineSeg.scriptLang;
                //
                //CACHING ...., reduce number of GSUB/GPOS
                //
                //we cache used line segment for a while
                //we ask for caching context for a specific typeface and font size
                GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                  lineSeg.StartAt,
                                                                                  lineSeg.Length);

                int seqLen = seq.Count;

                for (int s = 0; s < seqLen; ++s)
                {
                    UnscaledGlyphPlan glyphPlan = seq[s];

                    double actualAdvX = glyphPlan.AdvanceX;

                    outputTotalW +=
                        outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] +=
                            (int)Math.Round(actualAdvX * scale);
                }
                pos += lineSeg.Length;
            }

            //

            lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale);

            _reusableTextBuffer.SetRawCharBuffer(null);
        }
示例#13
0
        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);
        }
示例#14
0
        float ITextService.MeasureBlankLineHeight(RequestFont font)
        {
            LineSpacingChoice sel_linespcingChoice;
            Typeface          typeface = ResolveTypeface(font);

            return((int)(Math.Round(typeface.CalculateRecommendLineSpacing(out sel_linespcingChoice) *
                                    typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints))));
        }
示例#15
0
        public override void DrawFromGlyphPlans(GlyphPlanSequence seq, int startAt, int len, float x, float y)
        {
            UpdateVisualOutputSettings();

            //draw data in glyph plan
            //3. render each glyph

            float sizeInPoints = this.FontSizeInPoints;
            float pxscale      = _currentTypeface.CalculateScaleToPixelFromPointSize(sizeInPoints);

            //
            _glyphMeshCollections.SetCacheInfo(this.Typeface, sizeInPoints, this.HintTechnique);


            //this draw a single line text span***
            Graphics g = this.TargetGraphics;

            float cx = 0;
            float cy = 0;

            float baseline = y;

            var snapToPxScale = new GlyphPlanSequenceSnapPixelScaleLayout(seq, startAt, len, pxscale);

            while (snapToPxScale.Read())
            {
                if (!_glyphMeshCollections.TryGetCacheGlyph(snapToPxScale.CurrentGlyphIndex, out GraphicsPath foundPath))
                {
                    //if not found then create a new one
                    _currentGlyphPathBuilder.BuildFromGlyphIndex(snapToPxScale.CurrentGlyphIndex, sizeInPoints);
                    _txToGdiPath.Reset();
                    _currentGlyphPathBuilder.ReadShapes(_txToGdiPath);
                    foundPath = _txToGdiPath.ResultGraphicsPath;

                    //register
                    _glyphMeshCollections.RegisterCachedGlyph(snapToPxScale.CurrentGlyphIndex, foundPath);
                }
                //------
                //then move pen point to the position we want to draw a glyph


                cx = (float)Math.Round(snapToPxScale.ExactX + x);
                cy = (float)Math.Floor(snapToPxScale.ExactY + baseline);

                g.TranslateTransform(cx, cy);

                if (FillBackground)
                {
                    g.FillPath(_fillBrush, foundPath);
                }
                if (DrawOutline)
                {
                    g.DrawPath(_outlinePen, foundPath);
                }
                //and then we reset back ***
                g.TranslateTransform(-cx, -cy);
            }
        }
示例#16
0
 public NOpenFont(NOpenFontFace ownerFace, float sizeInPoints, FontStyle style)
 {
     this.ownerFace    = ownerFace;
     this.sizeInPoints = sizeInPoints;
     this.style        = style;
     this.typeFace     = ownerFace.Typeface;
     //calculate scale ***
     scale = typeFace.CalculateScaleToPixelFromPointSize(sizeInPoints);
 }
示例#17
0
 public NOpenFont(NOpenFontFace ownerFace, float sizeInPoints, FontStyle style)
 {
     _ownerFace    = ownerFace;
     _sizeInPoints = sizeInPoints;
     _style        = style;
     _typeFace     = ownerFace.Typeface;
     //calculate scale ***
     _scale = _typeFace.CalculateScaleToPixelFromPointSize(sizeInPoints);
     _recommendLineSpacing = _typeFace.CalculateRecommendLineSpacing() * _scale;
 }
示例#18
0
        void SetCurrentFontInfo(Typeface typeface, float sizeInPoints)
        {
            _typeface     = typeface;
            _sizeInPoints = sizeInPoints;

            //please note that DPI effect glyph size
            //TODO:
            //1. add information about dpi to generated texture
            //2. when dpi is changed we need to use correct texture for that dpi
            _currentDPI = Typeface.DefaultDpi;
            _px_scale   = _typeface.CalculateScaleToPixelFromPointSize(_sizeInPoints, (int)_currentDPI);
        }
示例#19
0
        public Typeface ResolveTypeface(RequestFont font)
        {
            //from user's request font
            //resolve to actual Typeface
            //get data from...
            //cache level-1 (attached inside the request font)
            Typeface typeface = PixelFarm.Drawing.Internal.RequestFontCacheAccess.GetActualFont <Typeface>(font, _system_id);

            if (typeface != null)
            {
                return(typeface);
            }
            //
            //cache level-2 (stored in this Ifonts)
            if (!_resolvedTypefaceCache.TryGetValue(font.FontKey, out typeface))
            {
                //not found ask the typeface store to load that font
                //....
                typeface = _txtServices.GetTypeface(font.Name, font.Style.ConvToInstalledFontStyle());
                if (typeface == null)
                {
                    throw new NotSupportedException();
                }
                //
                //cache here (level-1)
                _resolvedTypefaceCache.Add(font.FontKey, typeface);
            }
            //and cache into level-0

            float pxSize = Typeface.ConvPointsToPixels(font.SizeInPoints);

            float pxscale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            float recommedLineSpacingInPx = typeface.CalculateRecommendLineSpacing() * pxscale;
            float descentInPx             = typeface.Descender * pxscale;
            float ascentInPx  = typeface.Ascender * pxscale;
            float lineGapInPx = typeface.LineGap * pxscale;

            PixelFarm.Drawing.Internal.RequestFontCacheAccess.SetActualFont(font, _system_id, typeface);
            PixelFarm.Drawing.Internal.RequestFontCacheAccess.SetGeneralFontMetricInfo(font,
                                                                                       pxSize,
                                                                                       ascentInPx,
                                                                                       descentInPx,
                                                                                       lineGapInPx,
                                                                                       recommedLineSpacingInPx);

            TextBufferSpan w           = new TextBufferSpan(new char[] { ' ' });
            Size           whiteSpaceW = MeasureString(ref w, font);

            PixelFarm.Drawing.Internal.RequestFontCacheAccess.SetWhitespaceWidth(font, _system_id, whiteSpaceW.Width);
            return(typeface);
        }
示例#20
0
        public ResolvedFont(Typeface typeface, float sizeInPoints)
        {
            Typeface = typeface;
            if (typeface != null)
            {
                _px_scale = typeface.CalculateScaleToPixelFromPointSize(sizeInPoints);
                _ws       = (int)Math.Round(typeface.GetWhitespaceWidth() * _px_scale);
                Name      = typeface.Name;
            }

            SizeInPoints = sizeInPoints;

            RuntimeResolvedKey = CalculateGetHasCode(
                TypefaceExtensions.GetCustomTypefaceKey(typeface),
                sizeInPoints);
        }
示例#21
0
        public void ChangeFont(RequestFont font)
        {
            if (_font == font)
            {
                return;
            }
            //font has been changed,
            //resolve for the new one
            //check if we have this texture-font atlas in our MySimpleGLBitmapFontManager
            //if not-> request the MySimpleGLBitmapFontManager to create a newone
            _fontAtlas = _myGLBitmapFontMx.GetFontAtlas(font, out _glBmp);
            _font      = font;

            Typeface typeface = _textServices.ResolveTypeface(font);

            _px_scale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);
        }
        public void ChangeFont(RequestFont font)
        {
            if (_font == font || (_font != null && _font.FontKey == font.FontKey))
            {
                //not change -> then return
                return;
            }

            //_loadedFont = _loadFonts.RegisterFont(font);
            //System.Diagnostics.Debug.WriteLine(font.Name + font.SizeInPoints);

            //LoadedFont loadFont = _loadFonts.RegisterFont(font);
            //font has been changed,
            //resolve for the new one
            //check if we have this texture-font atlas in our MySimpleGLBitmapFontManager
            //if not-> request the MySimpleGLBitmapFontManager to create a newone
            _fontAtlas = _myGLBitmapFontMx.GetFontAtlas(font, out _glBmp);
            _font      = font;
            Typeface typeface = _textServices.ResolveTypeface(font);

            _px_scale = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);
        }
示例#23
0
 public override float GetScale(float pointSize) => _typeface.CalculateScaleToPixelFromPointSize(pointSize);
示例#24
0
        public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan,
                                                     ILineSegmentList lineSegs, RequestFont font,
                                                     int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight)
        {
            //layout
            //from font
            //resolve for typeface
            //
            Typeface typeface = ResolveTypeface(font);

            _txtServices.SetCurrentFont(typeface, font.SizeInPoints);


            MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs;
            float             scale      = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            outputTotalW = 0;
            int j   = mylineSegs.Count;
            int pos = 0; //start at 0

            _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer());

            for (int i = 0; i < j; ++i)
            {
                //userGlyphPlanList.Clear();
                //userCharToGlyphMapList.Clear();
                //get each segment
                MyLineSegment lineSeg = mylineSegs.GetSegment(i);
                //each line seg may has different script lang
                _txtServices.CurrentScriptLang = lineSeg.scriptLang;
                //
                //CACHING ...., reduce number of GSUB/GPOS
                //
                //we cache used line segment for a while
                //we ask for caching context for a specific typeface and font size
                GlyphPlanSequence seq = _txtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                  lineSeg.StartAt,
                                                                                  lineSeg.Length);


                //IMPORTANT
                //num of glyph may more or less than original user input char buffer
                //


                //float g_x = 0;
                //float g_y = 0;
                //int baseY = (int)Math.Round(y);
                //int n = glyphPlanSeq.len;
                //int endBefore = glyphPlanSeq.startAt + n;

                ////***
                //_glsx.SetAssociatedTextureInfo(_glBmp);

                //List<float> vboBufferList = new List<float>();
                //List<ushort> indexList = new List<ushort>();

                //for (int i = glyphPlanSeq.startAt; i < endBefore; ++i)
                //{
                //    GlyphPlanList glyphPlanList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(glyphPlanSeq);
                //    GlyphPlan glyph = glyphPlanList[i];

                //    Typography.Rendering.TextureGlyphMapData glyphData;
                //    if (!_fontAtlas.TryGetGlyphDataByCodePoint(glyph.glyphIndex, out glyphData))
                //    {
                //        //if no glyph data, we should render a missing glyph ***
                //        continue;
                //    }
                //    //if (scaleFromTexture != 1)
                //    //{

                //    //}
                //    //--------------------------------------
                //    //TODO: review precise height in float
                //    //--------------------------------------
                //    PixelFarm.Drawing.Rectangle srcRect = ConvToRect(glyphData.Rect);
                //    g_x = (float)(x + (glyph.ExactX * scale - glyphData.TextureXOffset) * scaleFromTexture); //ideal x
                //    g_y = (float)(y + (glyph.ExactY * scale - glyphData.TextureYOffset + srcRect.Height) * scaleFromTexture);


                //    //for sharp glyph
                //    //we adjust g_x,g_y to integer value
                //    //float g_y2 = (float)Math.Floor(g_y);

                //    g_x = (float)Math.Round(g_x);
                //    g_y = (float)Math.Floor(g_y);


                //    switch (textureKind)
                //    {
                //        case TextureKind.Msdf:

                //            _glsx.DrawSubImageWithMsdf(_glBmp,
                //                ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);

                //            break;
                //        case TextureKind.StencilGreyScale:

                //            //stencil gray scale with fill-color
                //            _glsx.DrawGlyphImageWithStecil(_glBmp,
                //             ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);

                //            break;
                //        case TextureKind.Bitmap:
                //            _glsx.DrawSubImage(_glBmp,
                //             ref srcRect,
                //                g_x,
                //                g_y,
                //                scaleFromTexture);
                //            break;
                //        case TextureKind.StencilLcdEffect:
                //            _glsx.WriteVboToList(
                //              vboBufferList,
                //              indexList,
                //              ref srcRect,
                //              g_x,
                //              g_y,
                //              scaleFromTexture);
                //            break;
                //    }
                //}
                ////---------


                int seqLen = seq.Count;

                for (int s = 0; s < seqLen; ++s)
                {
                    UnscaledGlyphPlan glyphPlan = seq[s];

                    double actualAdvX = glyphPlan.AdvanceX;

                    outputTotalW +=
                        outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] +=
                            (int)Math.Round(actualAdvX * scale);
                }
                pos += lineSeg.Length;
            }

            //

            lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale);

            _reusableTextBuffer.SetRawCharBuffer(null);
        }
示例#25
0
        public void RenderChar(char testChar, HintTechnique hint)
        {
            builder.SetHintTechnique(hint);
#if DEBUG
            GlyphBoneJoint.dbugTotalId        = 0;//reset
            builder.dbugAlwaysDoCurveAnalysis = true;
#endif
            _infoView.Clear();
            _latestHint = hint;
            _testChar   = testChar;
            //----------------------------------------------------
            //
            builder.Build(testChar, _sizeInPoint);
            var txToVxs1 = new GlyphTranslatorToVxs();
            builder.GlyphDynamicEdgeOffset = this.GlyphEdgeOffset;

            builder.ReadShapes(txToVxs1);

#if DEBUG
            var ps = txToVxs1.dbugGetPathWriter();
            _infoView.ShowOrgBorderInfo(ps.Vxs);
#endif
            PixelFarm.Drawing.VertexStore vxs = new PixelFarm.Drawing.VertexStore();

            txToVxs1.WriteOutput(vxs);
            //----------------------------------------------------

            //----------------------------------------------------
            painter.UseSubPixelLcdEffect = this.UseLcdTechnique;
            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            painter.Clear(PixelFarm.Drawing.Color.White);

            RectD bounds = new RectD();
            BoundingRect.GetBoundingRect(new PixelFarm.Drawing.VertexStoreSnap(vxs), ref bounds);
            //----------------------------------------------------
            float scale = _typeface.CalculateScaleToPixelFromPointSize(_sizeInPoint);
            _pxscale = scale;
            this._infoView.PxScale = scale;


            var   left2   = 0;
            int   floor_1 = (int)left2;
            float diff    = left2 - floor_1;
            //----------------------------------------------------
            if (OffsetMinorX)
            {
                MinorOffsetInfo = left2.ToString() + " =>" + floor_1 + ",diff=" + diff;
            }
            else
            {
                MinorOffsetInfo = left2.ToString();
            }


            //5. use PixelFarm's Agg to render to bitmap...
            //5.1 clear background
            painter.Clear(PixelFarm.Drawing.Color.White);

            if (FillBackGround)
            {
                //5.2
                painter.FillColor = PixelFarm.Drawing.Color.Black;

                float xpos = 5;// - diff;
                if (OffsetMinorX)
                {
                    xpos -= diff;
                }

                painter.SetOrigin(xpos, 10);
                painter.Fill(vxs);
            }
            if (DrawBorder)
            {
                //5.4
                painter.StrokeColor = PixelFarm.Drawing.Color.Green;
                //user can specific border width here...
                //5.5
                painter.Draw(vxs);
                //--------------
                int    markOnVertexNo = _infoView.DebugMarkVertexCommand;
                double x, y;
                vxs.GetVertex(markOnVertexNo, out x, out y);
                painter.FillRect(x, y, 4, 4, PixelFarm.Drawing.Color.Red);
                //--------------
                _infoView.ShowFlatternBorderInfo(vxs);
                //--------------
            }
#if DEBUG
            builder.dbugAlwaysDoCurveAnalysis = false;
#endif

            if (ShowTess)
            {
                RenderTessTesult();
            }

            //if (DrawDynamicOutline)
            //{
            //    GlyphDynamicOutline dynamicOutline = builder.LatestGlyphFitOutline;
            //    WalkDynamicOutline(painter, dynamicOutline, scale, DrawRegenerateOutline);

            //}
        }
示例#26
0
        public void CalculateUserCharGlyphAdvancePos(ref TextBufferSpan textBufferSpan,
                                                     ILineSegmentList lineSegs, RequestFont font,
                                                     int[] outputUserInputCharAdvance, out int outputTotalW, out int lineHeight)
        {
            //layout
            //from font
            //resolve for typeface
            //
            Typeface typeface = ResolveTypeface(font);

            _typographyTxtServices.SetCurrentFont(typeface, font.SizeInPoints);


            MyLineSegmentList mylineSegs = (MyLineSegmentList)lineSegs;
            float             scale      = typeface.CalculateScaleToPixelFromPointSize(font.SizeInPoints);

            outputTotalW = 0;
            int j   = mylineSegs.Count;
            int pos = 0; //start at 0

            _reusableTextBuffer.SetRawCharBuffer(textBufferSpan.GetRawCharBuffer());

            for (int i = 0; i < j; ++i)
            {
                //userGlyphPlanList.Clear();
                //userCharToGlyphMapList.Clear();
                //get each segment
                MyLineSegment lineSeg = mylineSegs.GetSegment(i);
                //each line seg may has different script lang
                _typographyTxtServices.CurrentScriptLang = lineSeg.scriptLang;
                //
                //CACHING ...., reduce number of GSUB/GPOS
                //
                //we cache used line segment for a while
                //we ask for caching context for a specific typeface and font size
                GlyphPlanSequence seq = _typographyTxtServices.GetUnscaledGlyphPlanSequence(_reusableTextBuffer,
                                                                                            lineSeg.StartAt,
                                                                                            lineSeg.Length);

                GlyphPlanList planList = GlyphPlanSequence.UnsafeGetInteralGlyphPlanList(seq);
                //IMPORTANT
                //num of glyph may more or less than original user input char buffer
                //


                int endAt       = seq.startAt + seq.len;
                int seq_startAt = seq.startAt;

                for (int s = seq_startAt; s < endAt; ++s)
                {
                    GlyphPlan glyphPlan  = planList[s];
                    float     tx         = glyphPlan.ExactX;
                    float     ty         = glyphPlan.ExactY;
                    double    actualAdvX = glyphPlan.AdvanceX;

                    outputTotalW +=
                        outputUserInputCharAdvance[pos + glyphPlan.input_cp_offset] +=
                            (int)Math.Round(actualAdvX * scale);
                }
                pos += lineSeg.Length;
            }

            //

            lineHeight = (int)Math.Round(typeface.CalculateRecommendLineSpacing() * scale);

            _reusableTextBuffer.SetRawCharBuffer(null);
        }
        //static void ConcatMeasureBox(ref float accumW, ref float accumH, ref MeasuredStringBox measureBox)
        //{
        //    accumW += measureBox.width;
        //    float h = measureBox.CalculateLineHeight();
        //    if (h > accumH)
        //    {
        //        accumH = h;
        //    }
        //}



        public static MeasuredStringBox LayoutAndMeasureString(
            this GlyphLayout glyphLayout,
            char[] textBuffer,
            int startAt,
            int len,
            float fontSizeInPoints,
            float limitW    = -1,//-1 unlimit scaled width (px)
            bool snapToGrid = true)
        {
            //1. unscale layout, in design unit
            glyphLayout.Layout(textBuffer, startAt, len);

            //2. scale  to specific font size

            Typeface typeface = glyphLayout.Typeface;
            float    pxscale  = typeface.CalculateScaleToPixelFromPointSize(fontSizeInPoints);

            //....
            float scaled_accumX = 0;

            if (limitW < 0)
            {
                //no limit
                scaled_accumX = MeasureGlyphPlans(
                    glyphLayout,
                    pxscale,
                    snapToGrid);

                return(new MeasuredStringBox(
                           scaled_accumX,
                           typeface.Ascender,
                           typeface.Descender,
                           typeface.LineGap,
                           typeface.ClipedAscender,
                           typeface.ClipedDescender,
                           pxscale));
            }
            else if (limitW > 0)
            {
                scaled_accumX = MeasureGlyphPlanWithLimitWidth(
                    glyphLayout,
                    pxscale,
                    limitW,
                    snapToGrid,
                    out int stopAtChar);

                var mstrbox = new MeasuredStringBox(
                    scaled_accumX,
                    typeface.Ascender,
                    typeface.Descender,
                    typeface.LineGap,
                    typeface.ClipedAscender,
                    typeface.ClipedDescender,
                    pxscale);

                mstrbox.StopAt = (ushort)stopAtChar;
                return(mstrbox);
            }
            else
            {
                return(new MeasuredStringBox(
                           0,
                           typeface.Ascender,
                           typeface.Descender,
                           typeface.LineGap,
                           typeface.ClipedAscender,
                           typeface.ClipedDescender,
                           pxscale));
            }
        }
 public override float GetScale(float pointSize)
 {
     return(typeface.CalculateScaleToPixelFromPointSize(pointSize));
 }
        public void Layout(IGlyphPositions posStream, PxScaledGlyphPlanList outputGlyphPlanList)
        {
            float pxscale = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints);

            if (!UseWithLcdSubPixelRenderingTechnique)
            {
                //layout without fit to alignment direction
                GlyphLayoutExtensions.GenerateGlyphPlans(posStream, pxscale, false, outputGlyphPlanList);
                return; //early exit
            }
            //------------------------------
            int finalGlyphCount = posStream.Count;

#if DEBUG
            float dbug_onepx = 1 / pxscale;
#endif
            //
            int   cx = 0;
            short cy = 0;
            //
            //at this state, we need exact info at this specific pxscale
            //
            _glyphMeshStore.SetFont(_typeface, this._fontSizeInPoints);
            FineABC current_ABC = new FineABC();
            FineABC prev_ABC    = new FineABC();

            for (int i = 0; i < finalGlyphCount; ++i)
            {
                short  input_offset, offsetX, offsetY, advW; //all from pen-pos
                ushort glyphIndex = posStream.GetGlyph(i, out input_offset, out offsetX, out offsetY, out advW);
                GlyphControlParameters controlPars = _glyphMeshStore.GetControlPars(glyphIndex);
                current_ABC.SetData(pxscale, controlPars, offsetX, offsetY, (ushort)advW);
                //-------------------------------------------------------------

                if (i > 0)
                {
                    //inter-glyph space
                    //ideal space
                    float ideal_space = prev_ABC.s_c + current_ABC.s_a;
                    //actual space
                    float actual_space = prev_ABC.m_c + current_ABC.m_a;

                    if (ideal_space < 0)
                    {
                        //f-f
                        //f-o
                        if (prev_ABC.s_c < 0)
                        {
                            ideal_space = 0 + current_ABC.s_a;
                        }
                        if (ideal_space < 0)
                        {
                            ideal_space = 0;
                        }
                    }
                    if (ideal_space >= 0)
                    {
                        //m-a
                        //i-i
                        //o-p
                        if (actual_space > 1.5 && actual_space - 0.5 > ideal_space)
                        {
                            cx--;
                        }
                        else
                        {
                            if (actual_space < ideal_space)
                            {
                                if (prev_ABC.final_advW + prev_ABC.m_c_adjust < prev_ABC.m_max)
                                {
                                    cx += current_ABC.m_a_adjust;
                                }
                            }
                            else
                            {
                                if (prev_ABC.final_advW - prev_ABC.m_c + prev_ABC.m_c_adjust > prev_ABC.m_max)
                                {
                                    cx += prev_ABC.m_c_adjust;
                                }
                            }
                        }
                    }
                    else
                    {
                        //this should not occur?
                    }
                }
                //-------------------------------------------------------------

                //TODO: review here again***


                float exact_x = (float)(cx + current_ABC.s_offsetX);
                float exact_y = (float)(cy + current_ABC.s_offsetY);

                //check if the current position can create a sharp glyph
                int   exact_x_floor   = (int)exact_x;
                float x_offset_to_fit = current_ABC.s_avg_x_ToFit;

                float final_x = exact_x_floor + x_offset_to_fit;
                if (UseWithLcdSubPixelRenderingTechnique)
                {
                    final_x += 0.33f;
                }

                outputGlyphPlanList.Append(new PxScaledGlyphPlan(
                                               input_offset,
                                               glyphIndex,
                                               (short)current_ABC.final_advW,
                                               (short)Math.Round(current_ABC.s_offsetX),
                                               (short)Math.Round(current_ABC.s_offsetY)
                                               ));
                //
                //
                cx += current_ABC.final_advW;
                //-----------------------------------------------
                prev_ABC = current_ABC;//copy current to prev
#if DEBUG
                prev_ABC.dbugIsPrev = true;
#endif
                // Console.WriteLine(exact_x + "+" + (x_offset_to_fit) + "=>" + final_x);
            }
        }
示例#30
0
        void CreateTextureFontFromGlyphIndices(
            Typeface typeface,
            float sizeInPoint,
            HintTechnique hintTechnique,
            SimpleFontAtlasBuilder atlasBuilder,
            bool applyFilter,
            ushort[] glyphIndices)
        {
            //sample: create sample msdf texture
            //-------------------------------------------------------------
            var builder = new GlyphPathBuilder(typeface);

            builder.SetHintTechnique(hintTechnique);
            //
            if (atlasBuilder.TextureKind == TextureKind.Msdf)
            {
                MsdfGenParams msdfGenParams = new MsdfGenParams();
                int           j             = glyphIndices.Length;
                for (int i = 0; i < j; ++i)
                {
                    ushort gindex = glyphIndices[i];
                    //create picture with unscaled version set scale=-1
                    //(we will create glyph contours and analyze them)
                    builder.BuildFromGlyphIndex(gindex, -1);
                    var glyphToContour = new GlyphContourBuilder();
                    builder.ReadShapes(glyphToContour);
                    //msdfgen with  scale the glyph to specific shapescale
                    msdfGenParams.shapeScale = 1f / 64; //as original
                    GlyphImage glyphImg = MsdfGlyphGen.CreateMsdfImage(glyphToContour, msdfGenParams);
                    //
                    atlasBuilder.AddGlyph(gindex, glyphImg);
                }
            }
            else
            {
                AggGlyphTextureGen aggTextureGen = new AggGlyphTextureGen();
                aggTextureGen.TextureKind = atlasBuilder.TextureKind;
                //create reusable agg painter***

                //assume each glyph size= 2 * line height
                //TODO: review here again...
                int tmpMemBmpHeight = (int)(2 * typeface.CalculateRecommendLineSpacing() * typeface.CalculateScaleToPixelFromPointSize(sizeInPoint));
                //create glyph img
                using (PixelFarm.CpuBlit.MemBitmap tmpMemBmp = new PixelFarm.CpuBlit.MemBitmap(tmpMemBmpHeight, tmpMemBmpHeight)) //square
                {
                    //draw a glyph into tmpMemBmp and then copy to a GlyphImage
                    aggTextureGen.Painter = PixelFarm.CpuBlit.AggPainter.Create(tmpMemBmp);
#if DEBUG
                    tmpMemBmp._dbugNote = "CreateGlyphImage()";
#endif

                    int j = glyphIndices.Length;
                    for (int i = 0; i < j; ++i)
                    {
                        //build glyph
                        ushort gindex = glyphIndices[i];
                        builder.BuildFromGlyphIndex(gindex, sizeInPoint);

                        GlyphImage glyphImg = aggTextureGen.CreateGlyphImage(builder, 1);
                        if (applyFilter)
                        {
                            glyphImg = Sharpen(glyphImg, 1);
                            //TODO:
                            //the filter make the image shift x and y 1 px
                            //temp fix with this,
                            glyphImg.TextureOffsetX += 1;
                            glyphImg.TextureOffsetY += 1;
                        }
                        //
                        atlasBuilder.AddGlyph(gindex, glyphImg);
                    }
                }
            }
        }