From: Cameron_C on 24 Dec 2009 08:17 Joe, thank you very much for sharing this. This answers everything I need to know about the calculations. Honestly, I have searched through Microsoft's documentation, but I did not find this explained. At least not in any meaningful way I could understand. After making the changes, the scaling is fine. I can print to two printers now. I am still not having much luck with my Brother printer. I will keep researching and I will post back anything I find. Merry Christmaas Joe, you have been very helpful all year long. Thanks, ........Cameron "Joseph M. Newcomer" wrote: > If you are doing a CreatePointFont, then its specification is to give the lfHeight as > decipixels. But that is a feature CreatePointFont (look at its code). So yes, if you are > giving font heights in decipoints, you want the / 10, but you had not actually indicated > that you were using decipoint heights. > > If you are doing CreateFontIndirect, you must use the actual height with the muldiv > computation. If you are doing CreatePointFont[Indirect] to a printer DC, the base > computations are already done for you, so you don't want to do them yourself; the result > will not be meaningful. > > Your choice of font height representation is yours. But remember that if you are doing > CreateFont[Indirect] you want the height in pixels, not decipixels. If you are doing > CreatePointFont[Indirect], its specificaiton is decipixels, in which case you would not be > doing a muldiv yourself. > > Ultimately, you are going to get a font in pixels. To get a 10-point font on a 10ppi > display, there is a 1:1 correspondence,but on a 600dpi display, to get a 10-point font it > would be 10 * (600/72). If you do this in floating point, you get 6000/72, and that is > essentially 83 pixels high. So if you single-step in far enough to > CreatePointFont[Indirect] you should see a real CreateFont creating a font which is the > right number of pixels for your device. An 18-point font would be 18*600/72 or about 150 > pixels high. Notice that the order matters. I tend to do computations in floating point > and then round them and convert back to an integer; saves all kinds of hassle with integer > truncation problems. > > If you are using MM_TWIPS, then you have 1440 pixels/inch, so an 18-point font is > 18*1440/72 = 360 pixels high. GDI takes care of mapping twips-based coordinates to > physical device coordinates. > > Note that if you are using a raw printer DC, the assumption is that you are using MM_TEXT. > So if you want to use CreatePointFont[Indirect] and specify a DC, the DC has to be in the > mapping mode you are going to use. Doesn't matter if it is TWIPS, LOENGLISH, HIENGLISH, > LMETRIC, HIMETRIC, or your own custom ISOTROPIC or ANISOTROPIC mapping, whatever mapping > you are going to use for the drawing is what should be set. Generally you do this in > OnPrepareDC, so you would call that at the point where you are about to create the font. > > Frankly, I would not waste any effort trying to create the font in advance of printing. > When I got into the OnDraw handler, after PrepareDC is called, that is the only place I > would create the fonts. They would not be member variables of the class; they would be > local variables of the OnDraw function. When I left OnDraw, they would be implicitly > destroyed by the destructors of the local variables. I would have no reason for them to > exist outside the context of OnDraw (or OnPaint). > joe > > > On Wed, 23 Dec 2009 12:51:01 -0800, Cameron_C <CameronC(a)discussions.microsoft.com> wrote: > > >Thanks Joe. > >What value should be in the lfHeight, when I am looking for a six point font? > >I know that I should use tenths of a point (so sixty) when I > >CreatePointFontIndirect. > >But, what do I want to put through the scaling math? Do I need tenths of a > >point? Or full point values? > >I believe that the MulDiv(a,b,c) is supposed to give me (a*b)/c. > >But, do I start with tenths of a point or point values? Six or sixty? > >When I use sixty, my font is now about one inch high. > >And when I use six, I get something pretty small. Maybe it is six points. > >And this is since I changed to set to MM_TWIPS after creating the printer DC. > >Maybe I should not use MM_TWIPS? > > > >Thanks, > > > > > >"Joseph M. Newcomer" wrote: > > > >> As pointed out, that divide-by-10 is a total disaster. Remove it. > >> joe > >> > >> On Wed, 23 Dec 2009 06:26:01 -0800, Cameron_C <CameronC(a)discussions.microsoft.com> wrote: > >> > >> >Thanks Joe, > >> >I removed the coding for the 42/13, and tried with the > >> > lfIniDefaults.lfHeight = -MulDiv(m_lfReportHeader.lfHeight/10, > >> >m_dc.GetDeviceCaps(LOGPIXELSY), 72); > >> >This gave me some print that was about a 2 point font. With glasses I could > >> >almost read some of it. > >> >But this is progress, at least something is printing. > >> > > >> >I also just found that if I use SetBkMode(TRANSPARENT) just before I begin > >> >to print, the report appears on my HP Photosmart printer. (Found it by > >> >accident when I accidentally uncommented the wrong line). > >> > > >> >When I print, I get a printer dc, then I define the fonts. The I select the > >> >font I want and I drawtext. > >> > > >> >This works fine on one printer. And, since I added the SetBkMode it works on > >> >another (although I have no understanding of why this would be). But still > >> >fails to print on my little Brother printer. > >> > > >> >One more curiousity, when I create font defaults, I do the following: > >> > CFont cfPrinterFont; > >> > m_bFlag = m_pApp->CreatePrinterDC(m_dc); > >> > > >> > /* Establish Default Font characteristics for the Reports */ > >> > cfPrinterFont.Attach(::GetStockObject(DEVICE_DEFAULT_FONT)); > >> > LOGFONT lf; > >> > cfPrinterFont.GetLogFont(&lf); > >> > > >> > lf.lfHeight *= 10; > >> > cfPrinterFont.Detach(); > >> > > >> > cfPrinterFont.CreatePointFontIndirect(&lf, &m_dc); > >> > cfPrinterFont.GetLogFont(&m_lfReportHeader); > >> >Now, later when I try to use the LOGFONT, I get characters that are the > >> >expected height, but are so thin they are unrecognizable. > >> *** > >> Never set lfWidth. Leave it 0 (default). Otherwise, you get the strange effects you are > >> seeing. > >> > >> You can download my font explorer and play with it, but you will see that lfWidth is not a > >> good value to use. > >> **** > >> >So, I reset the lfWidth to zero, in this LOGFONT structure, before I > >> >CreatePointFontIndirect. > >> >And, at least then I can see the characters. > >> >Why does the width need to be 0 (which requests the default)? I thought if I > >> >requested the DEVICE_DEFAULT_FONT for the printer DC, I would get all of the > >> >values I needed? > >> **** > >> TrueType/OpenType fonts will adjust themselves by horizontal scaling to conform to the > >> lfWidth if you do not default it. > >> **** > >> >Are there any other values I get in the LOGFONT that I should reset before > >> >creating a font? > >> > > >> >And then one more question. > >> >Maybe this is not an appropraite technique? I use a CFontDialog to allow the > >> >Users to select the fonts for the reports. > >> > LOGFONT lf = m_pPrinterControl->m_lfReportHeader; > >> > lf.lfHeight = -MulDiv(m_pPrinterControl->m_lfReportHeader.lfHeight/10, > >> >m_pDC->GetDeviceCaps(LOGPIXELSY), 72); > >> > CFontDialog fdHeader(&lf, > >> > CF_PRINTERFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT | CF_ENABLEHOOK > >> >| CF_FORCEFONTEXIST, > >> > m_pDC); > >> > > >> >Should the m_DC refer to the printerDC? Or to the display DC. > >> >I think it has to be the display but I am not sure? > >> **** > >> Ideally, the printer DC for selecting printer fonts. Again, get rid of the /10 (note this > >> is integer divide, so 18/10 = 1, which leads to your problems). But generally, if you use > >> the display, the fonts are available for the display. This dichotomy predates the > >> TrueType world, and in those days it allowed you to specify native printer fonts for > >> dot-matrix printers and primitive inkjet and laser printers. It is generally no longer an > >> issue. > >> joe > >> **** > >> > > >> >Thanks, > >> > > >> > > >> >"Joseph M. Newcomer" wrote: > >> > > >> >> See below... > >> >> On Tue, 22 Dec 2009 05:27:01 -0800, Cameron_C <CameronC(a)discussions.microsoft.com> wrote: > >> >> > >> >> >Hello Everyone. > >> >> >I have been struggling with this item for some time. > >> >> >For a while I was content to ignore it, but it has finally made it to the > >> >> >top of my list. > >> >> >I have an application where the User may choose reporting fonts. > >> >> >Three fonts. One for the header, one for the body, and one for the footer of > >> >> >the various reports. I save the LOGFONT structures for later use. > >> >> >At the time I do a StartDocument I grab the LOGFONT structures I had > >> >> >previously saved, and CreatePointFontIndirect to create the fonts. > >> >> >As I walk through the code in debug mode, everything seems to work fine. > >> >> >However, the printing works perfectly on an HP 9040DN, but no details appear > >> >> >when I print to a Brother or the HP Photosmart I have. The graphics boxes do > >> >> >appear though. > >> >> > > >> >> >Anyway my first question relates to the voodoo-like black magic of scaling > >> >> >the font. > >> >> >I want a ten point font. I select a ten point font from the CFontDialog, and > >> >> >save it. Later, when I want to create the font I call > >> >> >CreatePointFontIndirect, and I pass a value that is in tenths of a point. So, > >> >> >now I would pass 100, for my ten point font. > >> >> **** > >> >> The truth is that the font is scaled to the display. If you want to use that font on a > >> >> printer, you must scale it to the printer. > >> >> > >> >> Typically, you want to use CFont::CreatePointFontIndirect and for the second parameter > >> >> pass in your printer DC for printing and either NULL or your display DC for display. > >> >> ***** > >> >> >From experience this never worked. After poking through various web sites, I > >> >> >found someone had success with using a "Cook''s Constant" of 42/13. So, I > >> >> >have taken my value of 100, and multipled by 42/13. Is this obtuse or am I > >> >> >off base here? Anyway, this appears to do the trick, at least for the HP > >> >> >printer. > >> >> **** > >> >> Sounds like sheer luck. I have no idea what this is doing. > >> >> ***** > >> >> >I checked the Microsoft docs, and they suggest using something along the > >> >> >lines of -MulDiv(m_lfReportHeader.lfHeight/10, > >> >> >m_dc.GetDeviceCaps(LOGPIXELSY), 72); > >> >> >Now, I have tried this with the printers that do not deliver the report as > >> >> >execpted, and I see no difference. I have not tried this with the HP printer > >> >> >that is really working. > >> >> ***** > >> >> It may be a function of the printer dirvers, but it seems obtuse if it is. > >> >> **** > >> >> >Here is a code snippet showing how I have created the fonts. > >> >> > /* > >> >> > Assign default Report Header Font for the Reports > >> >> > Note: m_szIniSectionName will refer to the specific Report for the Printer. > >> >> > m_ProcessIni.m_szIniSectionName will refer to the DEFAULT entries > >> >> > for the Printer. > >> >> > */ > >> >> > LOGFONT lfIniDefaults; > >> >> > BOOL bFlag=FALSE; > >> >> > TEXTMETRIC myTextMetrics; > >> >> > > >> >> > m_ProcessIni.m_szIniKeyName.LoadString(IDS_REPORTHEADERFONT); > >> >> > bFlag = m_ProcessIni.getKeyValueForFont(&lfIniDefaults, > >> >> >m_ProcessIni.m_szIniKeyName, m_szIniSectionName); > >> >> **** > >> >> Have you considered the Registry for this? My Registry library actually saves some font > >> >> information automatically. I see no value in parsing font information from a .INI file (I > >> >> gave up doing that when I abandoned Win16 many years ago) > >> >> **** > >> >> > if (!bFlag) // No font information available from the ini file, so save > >> >> >DEFAULT > >> >> > { > >> >> > m_ProcessIni.setKeyValueForFont(m_plfReportHeader, > >> >> >m_ProcessIni.m_szIniKeyName, m_szIniSectionName); > >> >> > } > >> >> > else > >> >> > { > >> >> > m_lfReportHeader = lfIniDefaults; > >> >> > } > >> >> > lfIniDefaults = m_lfReportHeader; > >> >> > lfIniDefaults.lfHeight*=(42/13); // I have no idea why this scaling is > >> >> >required... But it is. Found this in a news group. > >> >> **** > >> >> Neither do I, it looks really bogus, like someone discovered some random value which gave > >> >> the illusion of working so claimed it made sense. 42/13 is silly anyway; 42/13 is 3, and > >> >> expressed as 42/13 doesn't change the fact it is 3. And I have no idea what 3 does. Now > >> >> 42.0/13.0, working as a double, e.g., > >> >> something =(int)( (double) something * 42.0 / 13.0) > >> >> might have meaning, but "3" is just silly. > >> >> **** > >> >> >// lfIniDefaults.lfHeight = -MulDiv(m_lfReportHeader.lfHeight/10, > >> >> >m_dc.GetDeviceCaps(LOGPIXELSY), 72); > >> >> **** > >> >> If you get rid of the gratutitous *=3, this should work correctly. But it is what > >> >> CreatePointFontIndirect does. Read the code. > >> >> **** > >> >> > > >> >> > /* > >> >> > Establish Font characteristics for the Report Header lines. > >> >> > lfIniDefaults Points to a LOGFONT structure that defines the > >> >> >characteristics > >> >> > of the logical font. > >> >> > The lfHeight member of the LOGFONT structure is measured in tenths of a > >> >> >point > >> >> > rather than logical units. > >> >> > (For instance, set lfHeight to 120 to request a 12-point font.) > >> >> > CreatePointFontIndirect returns non-zero when successful. > >> >> > If bFlag is zero, we have a problem! > >> >> > */ > >> >> > CFont*pOldHeaderFont, *pOldFooterFont, *pOldBodyFont; > >> >> ***** > >> >> Never use commas in declaration lists. And there is no reason to save old state like > >> >> "OldHeaderFont"; instead, use CDC::SaveDC and CDC::RestoreDC to mainain the purity of your > >> >> DC. > >> >> **** > >> >> > > >> >> > m_cfReportHeader.DeleteObject(); > >> >> > bFlag = m_cfReportHeader.CreatePointFontIndirect(&lfIniDefaults, &m_dc); > >> >> **** > >> >> OK, you Are using CreatePointFontIndirect, so why all that other stuff which either > >> >> duplicates it or duplicates it badly? > >> >> **** > >> >> > pOldHeaderFont = m_dc.SelectObject(&m_cfReportHeader); > >> >> **** > >> >> I have not saved an "old setting" on SelectObject in about 20 years. Use > >> >> SaveDC/RestoreDC. Otherwise, you get a lot of garbage variables and lose track of them > >> >> (there are over 30 DC parameters you might want to save the "old" version of!) > >> >> **** > >> >> > m_pcfReportHeader = &m_cfReportHeader; > >> >> ***** > >> >> How in the world does this assigment make any sense whatsoever? It is complete nonsense. > >> >> Get rid of it. > >> >> **** > >> >> > // m_hFontReportHeader is the CGdiObject public data member that stores > >> >> >the handle > >> >> > m_hFontReportHeader = (HFONT) pOldHeaderFont->GetSafeHandle(); > >> >> ***** > >> >> This makes even less sense. Why do you need an HFONT anyway? There is something > >> >> seriously wrong hwere with what you are doing. > >> >> **** > >> >> > //m_hFontReportHeader = (HFONT) m_pcfReportHeader->GetSafeHandle(); > >> >> > /* Get Average size of printed text for the Header Font */ > >> >> > m_dc.GetTextMetrics(&myTextMetrics); > >> >> > m_yLineHeader = myTextMetrics.tmHeight; > >> >> > > >> >> >Later when I want to use the font in a report, I select the font, and do a > >> >> >DrawText. > >> >> >Here is a code snippet: > >> >> > pcfOriginal = > >> >> >ts->_this->PrinterControl.m_dc.SelectObject(ts->_this->PrinterControl.m_pcfReportHeader);
First
|
Prev
|
Pages: 1 2 3 Prev: Missing symbol _iob (and others) Next: GDI/GDI+ stop drawing after a while on Windows 7 |