//// DspMetric.CPP - Display font metrics // // #include "precomp.hxx" #include "global.h" void AnnotateHeight( Graphics &g, Color c, Font &f, REAL x, REAL y1, REAL y2, WCHAR *id ) { SolidBrush brush(c); Pen pen(&brush, 2.0); pen.SetLineCap(LineCapArrowAnchor, LineCapArrowAnchor, DashCapFlat); g.DrawLine(&pen, x,y1, x,y2); g.DrawString(id,-1, &f, PointF(x,(y1+y2)/2), NULL, &brush); } void PaintMetrics( HDC hdc, int *piY, RECT *prc, int iLineHeight) { int icpLineStart; // First character of line int icpLineEnd; // End of line (end of buffer or index of CR character) HFONT hFont; HFONT hOldFont; LOGFONT lf; INT row; INT column; // Establish available width and height in device coordinates int DrawingWidth = prc->right - prc->left; int DrawingHeight = prc->bottom - *piY; // Establish a Graphics with 0,0 at the top left of the drawing area Graphics g(hdc); Matrix matrix; g.ResetTransform(); g.SetPageUnit(UnitPixel); g.TranslateTransform(REAL(prc->left), REAL(*piY)); // Clear the background RectF rEntire(0, 0, REAL(DrawingWidth), REAL(DrawingHeight)); SolidBrush whiteBrush(Color(0xff, 0xff, 0xff)); g.FillRectangle(&whiteBrush, rEntire); // Leave a little space for right and bottom margins DrawingWidth -= DrawingWidth/40; DrawingHeight -= DrawingHeight/40; Color blackColor(0, 0, 0); SolidBrush blackBrush(blackColor); Pen blackPen(&blackBrush, 2.0); Color grayColor(0xc0, 0xc0, 0xc0); SolidBrush grayBrush(grayColor); Pen grayPen(&grayBrush, 2.0); // Measure the string to see how wide it would be FontFamily family(g_style[0].faceName); StringFormat format(StringFormat::GenericTypographic()); format.SetFormatFlags(g_formatFlags | StringFormatFlagsNoWrap | StringFormatFlagsLineLimit); format.SetAlignment(g_align); RectF bounds; // Since we've chosen a size of 1.0 for the font height, MeasureString // will return the width as a multiple of the em height in bounds.Width. g.MeasureString( g_wcBuf, g_iTextLen, &Font(&family, 1.0, g_style[0].style, UnitWorld), PointF(0, 0), &format, &bounds ); // Establish font metrics if (family.IsStyleAvailable(g_style[0].style)) { // Establish line and cell dimensions in units INT emHeight = family.GetEmHeight(g_style[0].style); INT cellAscent = family.GetCellAscent(g_style[0].style); INT cellDescent = family.GetCellDescent(g_style[0].style); INT lineSpacing = family.GetLineSpacing(g_style[0].style); #if TEXTV2 INT typoAscent = family.GetTypographicAscent(g_style[0].style); INT typoDescent = family.GetTypographicDescent(g_style[0].style); INT typoLineGap = family.GetTypographicLineGap(g_style[0].style); if (typoDescent < 0) { typoDescent = -typoDescent; } INT typoLineSpacing = typoAscent + typoDescent + typoLineGap; #endif INT cellHeight = cellAscent + cellDescent; // We will display two lines from top of upper cell to bottom of lower // cell, with the lines separated by the typographic ascent + descent + // line gap. INT totalHeightInUnits = lineSpacing + cellHeight; REAL scale = REAL(DrawingHeight) / REAL(totalHeightInUnits); REAL worldEmHeight = emHeight * scale; // Now allow for the width of the string - if it would be wider than // the available DrawingWIdth, reduce the font size proportionately. if (worldEmHeight * bounds.Width > DrawingWidth) { REAL reduceBy = DrawingWidth / (worldEmHeight * bounds.Width); scale *= reduceBy; worldEmHeight = emHeight * scale; } Font font(&family, worldEmHeight, g_style[0].style, UnitWorld); // Draw two lines of text g.DrawString( g_wcBuf, g_iTextLen, &font, RectF(0, 0, REAL(DrawingWidth), REAL(DrawingHeight)), &format, &blackBrush ); g.DrawString( g_wcBuf, g_iTextLen, &font, RectF(0, lineSpacing * scale, REAL(DrawingWidth), REAL(DrawingHeight)), &format, &grayBrush ); // Draw lines REAL y=0; g.DrawLine(&blackPen, 0.0,y, REAL(DrawingWidth-1),y); // Draw lines for second row first, in case they're oblitereated by first row. y = scale * (lineSpacing); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (lineSpacing + cellAscent); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (lineSpacing + cellHeight); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); g.DrawLine(&blackPen, 0.0,0.0, REAL(DrawingWidth-1),0.0); y = scale * (cellAscent); g.DrawLine(&blackPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (cellHeight); g.DrawLine(&blackPen, 0.0,y, REAL(DrawingWidth-1),y); // Add construction lines. Font annotationFont(FontFamily::GenericSansSerif(), 10, 0, UnitPoint); Color darkGrayColor(0x80, 0x80, 0x80); AnnotateHeight(g, darkGrayColor, annotationFont, REAL(DrawingWidth/100.0), 0, scale*cellAscent, L"ascent"); AnnotateHeight(g, darkGrayColor, annotationFont, REAL(DrawingWidth/100.0), scale*cellAscent, scale*cellHeight, L"descent"); AnnotateHeight(g, darkGrayColor, annotationFont, REAL(95*DrawingWidth/100.0), 0, scale*lineSpacing, L"line spacing"); AnnotateHeight(g, darkGrayColor, annotationFont, REAL(DrawingWidth/10.0), scale*(cellHeight-emHeight), scale*cellHeight, L"Em Height"); #if TEXTV2 y = scale * (cellAscent - typoAscent); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (cellAscent + typoDescent); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (lineSpacing + cellAscent - typoAscent); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); y = scale * (lineSpacing + cellAscent + typoDescent); g.DrawLine(&grayPen, 0.0,y, REAL(DrawingWidth-1),y); #endif // Test font.GetHeight REAL fontHeight = font.GetHeight(&g); g.DrawLine(&blackPen, REAL(DrawingWidth-1),0.0, REAL(DrawingWidth-1),fontHeight); } *piY += 41*DrawingHeight/40; }