/// <summary> /// <para>Finds the right font size to fit characters (2x5 with default size, but it varies).</para> /// <para>Finds right vertical area based on font's actual display properties.</para> /// </summary> private void calibrateFont() { float width = Width; fontSize = 10.0F; // Measuring artefacts using (Bitmap bmp = new Bitmap(1, 1)) using (Graphics g = Graphics.FromImage(bmp)) { StringFormat sf = StringFormat.GenericTypographic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // Keep growing font until we reach a comfortable width while (true) { //var xsi = HanziMeasure.Instance.GetMeasures(fontFace, fontSize); //charSize = xsi.RealRect.Size; charSize = HanziRenderer.GetCharSize(Magic.ZhoContentFontFamily, fontSize); if (charSize.Width * 5.0F >= width * 0.9F) { break; } fontSize += 0.5F; } } // Width of rectangle: using my space equally float rectWidth = (width - 2.0F) / 5.0F; // Height of rectange: depends on font's actual drawing behavior! float rectHeight = charSize.Height; // Horizontal padding is rectangle width minus measured char width, over two float hPad = (rectWidth - charSize.Width) / 2.0F; // Add twice horizontal padding to rectangle height; offset chars from top by padding rectHeight += 2.0F * hPad; lock (animLO) { for (int i = 0; i != 5; ++i) { float x = ((float)i) * rectWidth + 1.0F; RectangleF rtop = new RectangleF(x, 1.0F, rectWidth, rectHeight); RectangleF rbot = new RectangleF(x, rectHeight + 1.0F, rectWidth, rectHeight); charRects[i].Rect = rtop; charRects[i + 5].Rect = rbot; } } charOfsX = (rectWidth - charSize.Width) / 2.0F; charOfsY = (rectHeight - charSize.Height) / 2.0F; Height = (int)Math.Round((rectHeight) * 2.0F + 0.5F); MakeMePaint(false, RenderMode.Invalidate); }
/// <summary> /// Analyzes layout of headword. /// </summary> /// <param name="g">A Graphics object used for measurements.</param> private void doAnalyzeHeadword(Graphics g) { // If already analyzed, nothing to do if (headInfo != null) { return; } // This is how we measure StringFormat sf = StringFormat.GenericTypographic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; // On-demand: measure a single ideograph's dimensions // We only measure simplified. Assume simplified and traditional fonts come in matching pairs -> same size. if (ideoSize.Width == 0) { ideoSize = HanziRenderer.GetCharSize(Magic.ZhoContentFontFamily, Magic.ZhoResultFontSize); float hanziLinePad = 6.0F; hanziLinePad *= scale; ideoLineHeight = ideoSize.Height + hanziLinePad; } headInfo = new HeadInfo(); if (analyzedScript == SearchScript.Simplified) { headInfo.HeadMode = HeadMode.OnlySimp; } else if (analyzedScript == SearchScript.Traditional) { headInfo.HeadMode = HeadMode.OnlyTrad; } else { headInfo.HeadMode = HeadMode.BothSingleLine; } //// For width of headword, use padLeft from border, plus 4 to 6 ideographs' worth of space //// Depending on longest headword in entire list //int hwChars = maxHeadLength; //if (hwChars < 4) hwChars = 4; //if (hwChars > 6) hwChars = 6; //float hwidth = ((float)hwChars) * ideoSize.Width; // Revised // For width of headword, always take 5 characters' width of space float hwidth = 5.0F * ideoSize.Width; headInfo.HeadwordRight = padLeft + hwidth; // Measure simplified chars from start; break when needed PointF loc = new PointF(((float)padLeft) + ideoSize.Width, padTop); bool lbrk = false; if (analyzedScript == SearchScript.Simplified || analyzedScript == SearchScript.Both) { lbrk |= doAnalyzeHanzi(g, entry.ChSimpl, true, sf, headInfo.SimpBlocks, ref loc, headInfo.HeadwordRight); } if (analyzedScript == SearchScript.Traditional || analyzedScript == SearchScript.Both) { //loc.X = padLeft; loc.X = ((float)padLeft) + ideoSize.Width; if (analyzedScript == SearchScript.Both) { loc.Y += ideoLineHeight; } lbrk |= doAnalyzeHanzi(g, entry.ChTrad, false, sf, headInfo.TradBlocks, ref loc, headInfo.HeadwordRight); } // If we're displaying both simplified and traditional, fade out // traditional chars that are same as simplified, right above them if (analyzedScript == SearchScript.Both) { for (int i = 0; i != headInfo.SimpBlocks.Count; ++i) { if (headInfo.SimpBlocks[i].Char == headInfo.TradBlocks[i].Char) { headInfo.TradBlocks[i].Faded = true; } } } // Bottom of headword area headInfo.HeadwordBottom = loc.Y + ideoLineHeight; // If we had a line break and we're showing both scripts, update info if (analyzedScript == SearchScript.Both && lbrk) { headInfo.HeadMode = HeadMode.BothMultiLine; } }