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; } }
public void Layout(IGlyphPositions posStream, GlyphPlanList outputGlyphPlanList) { if (!UseWithLcdSubPixelRenderingTechnique) { //layout without fit to alignment direction LayoutWithoutHorizontalFitAlign(posStream, outputGlyphPlanList); return; //early exit } //------------------------------ int finalGlyphCount = posStream.Count; float pxscale = _typeface.CalculateScaleToPixelFromPointSize(this._fontSizeInPoints); #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 // _hintedFontStore.SetFont(_typeface, this._fontSizeInPoints); FineABC current_ABC = new FineABC(); FineABC prev_ABC = new FineABC(); 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); GlyphControlParameters controlPars = _hintedFontStore.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? } } //------------------------------------------------------------- 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 GlyphPlan( glyphIndex, final_x, exact_y, current_ABC.final_advW)); // // 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); } }