/// <summary> /// Calculates pinyin layout. /// </summary> private void doAnalyzePinyin(Graphics g) { // If already measured, nothing to do if (pinyinInfo != null) { return; } // This is how we measure StringFormat sf = StringFormat.GenericTypographic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; pinyinInfo = new PinyinInfo(); // Measure each pinyin syllable bool diacritics = true; var pcoll = entry.GetPinyinForDisplay(diacritics, res.PinyinHiliteStart, res.PinyinHiliteLength, out pinyinInfo.HiliteStart, out pinyinInfo.HiliteLength); float cx = headInfo.HeadwordRight + (float)padMid; float ctop = padTop; for (int i = 0; i != pcoll.Count; ++i) { PinyinSyllable ps = pcoll[i]; // New pinyin block PinyinBlock pb = new PinyinBlock(); // Text: syllable's display text string text = ps.GetDisplayString(true); pb.TextPos = textPool.PoolString(text); // If text is punctuation, glue it to previous syllable if (text.Length == 1 && CedictFormatter.SticksLeft(text) && i > 0) { cx -= pinyinSpaceWidth; } // Block's size and relative location SizeF sz = g.MeasureString(text, getFont(fntPinyinHead), 65535, sf); pb.Rect = new RectangleF(cx, ctop, sz.Width, sz.Height); cx += sz.Width + pinyinSpaceWidth; // Add block pinyinInfo.Blocks.Add(pb); } // Height of whole pinyin area pinyinInfo.PinyinHeight = pinyinInfo.Blocks[0].Rect.Height; }
/// <summary> /// Calculates pinyin layout. /// </summary> private void doAnalyzePinyin(Graphics g) { // If already measured, nothing to do if (pinyinInfo != null) return; // This is how we measure StringFormat sf = StringFormat.GenericTypographic; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; pinyinInfo = new PinyinInfo(); // Measure each pinyin syllable bool diacritics = true; var pcoll = entry.GetPinyinForDisplay(diacritics, res.PinyinHiliteStart, res.PinyinHiliteLength, out pinyinInfo.HiliteStart, out pinyinInfo.HiliteLength); float cx = headInfo.HeadwordRight + (float)padMid; float ctop = padTop; for (int i = 0; i != pcoll.Count; ++i) { PinyinSyllable ps = pcoll[i]; // New pinyin block PinyinBlock pb = new PinyinBlock(); // Text: syllable's display text string text = ps.GetDisplayString(true); pb.TextPos = textPool.PoolString(text); // If text is punctuation, glue it to previous syllable if (text.Length == 1 && CedictFormatter.SticksLeft(text) && i > 0) cx -= pinyinSpaceWidth; // Block's size and relative location SizeF sz = g.MeasureString(text, getFont(fntPinyinHead), 65535, sf); pb.Rect = new RectangleF(cx, ctop, sz.Width, sz.Height); cx += sz.Width + pinyinSpaceWidth; // Add block pinyinInfo.Blocks.Add(pb); } // Height of whole pinyin area pinyinInfo.PinyinHeight = pinyinInfo.Blocks[0].Rect.Height; }
/// <summary> /// Paint headword's pinyin, with highlights. /// </summary> private void doPaintPinyin(Graphics g, Brush bfont, SolidBrush bhilite, StringFormat sf, Color bgcol) { if (pinyinInfo == null || pinyinInfo.Blocks.Count == 0) { return; } // We do have highlights if (pinyinInfo.HiliteStart != -1) { // We offset highlight vertically for more pleasing aesthetics (lots of empty space at top in text) float topOfs = pinyinInfo.Blocks[0].Rect.Height / 15.0F; // TO-DO: This will need more work; depends on font size & Scale // We make highlight exten a bit farther down float hFactor = 1.1F; // Needed to make gradient work g.SmoothingMode = SmoothingMode.None; float edgeLeft = 0; float edgeRight = 0; for (int i = 0; i != pinyinInfo.Blocks.Count; ++i) { // Not in highlight now if (i < pinyinInfo.HiliteStart || i >= pinyinInfo.HiliteStart + pinyinInfo.HiliteLength) { continue; } // Get block PinyinBlock pb = pinyinInfo.Blocks[i]; // Where? PointF loc = pb.Rect.Location; loc.Y += topOfs; // Remember edges if (i == pinyinInfo.HiliteStart) { edgeLeft = pb.Rect.Left; } if (i + 1 == pinyinInfo.HiliteStart + pinyinInfo.HiliteLength) { edgeRight = pb.Rect.Right; } // Hilight syllable itself RectangleF hlr = new RectangleF(loc, pb.Rect.Size); hlr.Height *= hFactor; g.FillRectangle(bhilite, hlr); // For middle and last: hilight space before if (i > pinyinInfo.HiliteStart) { float xprev = pinyinInfo.Blocks[i - 1].Rect.Right; hlr.X = xprev; hlr.Width = loc.X - xprev; g.FillRectangle(bhilite, hlr); } } // Left and right edges: gradient // Extends one space's width beyond edge // Reach max color two spaces' width within syllable, OR // by midpoint, if edgeRight - edgeLeft < 4 spaces float y = pinyinInfo.Blocks[0].Rect.Top + topOfs; float w = pinyinSpaceWidth; if (edgeLeft != 0 && edgeRight != 0) { float midPoint = (edgeLeft + edgeRight) / 2.0F; float whalf = (edgeRight - edgeLeft) / 2.0F; RectangleF rleft; if (whalf < 2.0F * w) { rleft = new RectangleF(edgeLeft - w, y, w + whalf, pinyinInfo.PinyinHeight * hFactor); } else { rleft = new RectangleF(edgeLeft - w, y, w * 3.0F, pinyinInfo.PinyinHeight * hFactor); } using (LinearGradientBrush lbr = new LinearGradientBrush(rleft, bgcol, Magic.HiliteColor, LinearGradientMode.Horizontal)) { g.FillRectangle(lbr, rleft); } RectangleF rright; if (whalf < 2.0F * w) { rright = new RectangleF(midPoint, y, w + whalf, pinyinInfo.PinyinHeight * hFactor); } else { rright = new RectangleF(edgeRight - 2.0F * w, y, w * 3.0F, pinyinInfo.PinyinHeight * hFactor); } using (LinearGradientBrush lbr = new LinearGradientBrush(rright, Magic.HiliteColor, bgcol, LinearGradientMode.Horizontal)) { g.FillRectangle(lbr, rright); } } } // Now, write each syllable - so it goes on top of hilites foreach (PinyinBlock pb in pinyinInfo.Blocks) { PointF loc = pb.Rect.Location; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; // Draw string g.DrawString(textPool.GetString(pb.TextPos), getFont(fntPinyinHead), bfont, loc, sf); } }