/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* AbiSource Application Framework * Copyright (C) 2001,2002 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include #include #include "ut_types.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "ut_string.h" #include "ut_misc.h" #include "xap_Strings.h" #include "xap_UnixGnomePrintGraphics.h" #include "xap_EncodingManager.h" #include "gr_UnixGnomeImage.h" #include "ut_string_class.h" #include "xap_UnixDialogHelper.h" #include /***********************************************************************/ /* This file provides an interface into Gnome Print */ /***********************************************************************/ #define OUR_LINE_LIMIT 200 /* FIXME: UGLY UGLY UGLY, but we need to fix the PrintPrivew show bug. Test it with something like 7 when to see what is the problem with PP. The show operator in print preview does not move th currentpoint. Chema */ // the resolution that we report to the application (pixels per inch). #define GPG_RESOLUTION 7200 #define GPG_DEFAULT_FONT "Nimbus Roman No9 L" /*************************************************************************/ // Map font specic encoding to Unicode for gnome-print /*************************************************************************/ struct _encUnicode { UT_uint32 fontcode; // Font specific code UT_uint32 unicode; // True unicode value }; /***********************************************************************/ /* map abi's fonts to gnome fonts, or at least try to */ /***********************************************************************/ struct _fontMapping { char *abi; // what abiword calls a font's name char *gnome; // what gnome refers to it as (or a close substitute) }; // mapping of the fonts that abi ships with // to what gnome-font ships with /* The ones with ?? have not been verified. (Chema) */ static struct _fontMapping fontMappingTable[] = { {"Arial", "Nimbus Sans L"}, // Arial is a MS name for Helvetica, //v {"Bitstream", "Bitstream Charter"}, // ?? // v {"Bookman", "URW Bookman L"}, // v {"Century Schoolbook", "Century Schoolbook L"}, //v {"Courier", "Nimbus Mono L"}, //v {"Courier New", "Nimbus Mono L"}, /* ??? not really. (I think) */ //v {"Dingbats", "Dingbats"}, // v {"Goth", "URW Gothic L"}, // v {"Helvetic", "Nimbus Sans L"}, // v {"Helvetica", "Nimbus Sans L"}, // v {"Nimbus Mono", "Nimbus Mono L"}, // v {"Nimbus Roman", "Nimbus Roman No9 L"}, //v {"Nimbus Sans", "Nimbus Sans L"}, // v {"Nimbus Sans Condensed", "Nimbus Sans L"}, // v This name is Nimbus Sans L * Condensed!! {"Palladio", "URW Palladio L"}, // v {"Standard Symbols", "Standard Symbols L"}, // v {"Symbol", "Standard Symbols L"}, // v {"Times", "Nimbus Roman No9 L"}, // v {"Times New Roman", "Nimbus Roman No9 L"}, //v {"*", GPG_DEFAULT_FONT} }; #define TableSize ((sizeof(fontMappingTable)/sizeof(fontMappingTable[0]))) static char * mapFontName(const char *name) { unsigned int idx = 0; // if we're passed crap, default to some normal font if(!name || !*name) { return GPG_DEFAULT_FONT; } UT_uint32 k; for (k=0; k p2 */ static UT_sint32 compareCodes( const void * p1, const void * p2) { _encUnicode ** sP1 = (_encUnicode **) const_cast(p1); _encUnicode ** sP2 = (_encUnicode **) const_cast(p2); return (UT_sint32) (*sP1)->fontcode - (UT_sint32) (*sP2)->fontcode; } static bool isItalic(XAP_UnixFont::style s) { return ((s == XAP_UnixFont::STYLE_ITALIC) || (s == XAP_UnixFont::STYLE_BOLD_ITALIC)); } static GnomeFontWeight getGnomeFontWeight(XAP_UnixFont::style s) { GnomeFontWeight w = GNOME_FONT_BOOK; switch((int)s) { case XAP_UnixFont::STYLE_BOLD_ITALIC: case XAP_UnixFont::STYLE_BOLD: w = GNOME_FONT_BOLD; default: break; } return w; } #define DEFAULT_GNOME_FONT "Helvetica" static gboolean fonts_match(GnomeFont *tmp, const gchar * intended) { /* this is a hack - gnome_font_new_closest() returns Helvetica when it gets confused */ if(!g_strcasecmp(intended, DEFAULT_GNOME_FONT)) return TRUE; // asked for and got helvetica const gchar * what = gnome_font_get_name(tmp); xxx_UT_DEBUGMSG(("Looking for %s returned %s \n",intended,what)); if(!g_strcasecmp(what, DEFAULT_GNOME_FONT)) return FALSE; // asked for something and got helvetica instead return TRUE; } #undef DEFAULT_GNOME_FONT GnomeFont * XAP_UnixGnomePrintGraphics::_allocGnomeFont(PSFont* pFont) { XAP_UnixFont *uf = pFont->getUnixFont(); XAP_UnixFont::style style = uf->getStyle(); char *abi_name = (char*)uf->getName(); GnomeFontWeight gfw = getGnomeFontWeight(style); bool italic = isItalic(style); // ok, this is the ugliest hack of the year, so I'll take it one step // at a time double size = (double)pFont->getSize() * _scale_factor_get (); // first try to directly allocate abi's name // this is good for fonts not in my table, and // fonts installed by the user in both Abi and // using gnome-font-install GnomeFont *tmp = NULL; /* gnome_font_new_closest always returns a font. So you will get helvetica if not found */ tmp = gnome_font_new_closest(abi_name, gfw, italic, size); // assert that the fonts match if(tmp && fonts_match(tmp, abi_name)) return tmp; xxx_UT_DEBUGMSG(("Dom: unreffing gnome font: ('%s','%s')\n", gnome_font_get_ps_name(tmp), abi_name)); // else we got something we didn't ask for // unref the gnome-font and try again gnome_font_unref(tmp); char *fontname = mapFontName(abi_name); tmp = gnome_font_new_closest(fontname, gfw, italic, size); return tmp; } XAP_UnixGnomePrintGraphics::~XAP_UnixGnomePrintGraphics() { // unref the resource if(m_pCurrentFont != NULL && GNOME_IS_FONT(m_pCurrentFont)) gnome_font_unref(m_pCurrentFont); UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncDingbats); UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncSymbol); } struct pageSizeMapping { char * abi; char * gnome; }; static struct pageSizeMapping paperMap[] = { {"Letter", "US-Letter"}, {"Legal", "US-Legal"}, {"Folio", "Executive"}, // i think that this is correct {NULL, NULL} }; #define PaperTableSize ((sizeof(paperMap)/sizeof(paperMap[0]))) // This method maps Abi's paper sizes to their gnome-print // equivalents if there is a mapping. If @sz is null, // return the default name. If @sz is not in our map, return @sz static const char * mapPageSize (const char * sz) { if (!sz && !*sz) return gnome_paper_name_default (); for (int i = 0; i < (int)PaperTableSize; i++) { if (paperMap[i].abi && !g_strcasecmp (sz, paperMap [i].abi)) return paperMap[i].gnome; } return sz; } #undef PaperTableSize XAP_UnixGnomePrintGraphics::XAP_UnixGnomePrintGraphics(GnomePrintContext *gpc, XAP_UnixFontManager * fontManager, XAP_App *pApp) { m_gpm = NULL; m_gpc = gpc; m_paper = NULL; m_bIsPreview = false; m_fm = fontManager; m_bStartPrint = false; m_bStartPage = false; m_pCurrentFont = NULL; m_pCurrentPSFont = NULL; if(m_vecEncSymbol.getItemCount()>0) m_vecEncSymbol.clear(); if(m_vecEncDingbats.getItemCount()>0) m_vecEncDingbats.clear(); m_cs = GR_Graphics::GR_COLORSPACE_COLOR; m_currentColor.m_red = 0; m_currentColor.m_grn = 0; m_currentColor.m_blu = 0; // // Now I need to load in the translations to unicode for Dingbats and Symbols. // loadUnicodeData(); } XAP_UnixGnomePrintGraphics::XAP_UnixGnomePrintGraphics(GnomePrintMaster *gpm, const char * pageSize, XAP_UnixFontManager * fontManager, XAP_App *pApp, bool isPreview) { m_pApp = pApp; m_gpm = gpm; m_gpc = gnome_print_master_get_context(gpm); // TODO: be more robust about this const GnomePaper * paper = gnome_paper_with_name(mapPageSize (pageSize)); xxx_UT_DEBUGMSG(("DOM: mapping '%s' returned '%s'\n", pageSize, mapPageSize (pageSize))); if (!paper) paper = gnome_paper_with_name (gnome_paper_name_default ()); UT_ASSERT(paper); m_paper = paper; gnome_print_master_set_paper(m_gpm, paper); m_bIsPreview = isPreview; m_fm = fontManager; m_bStartPrint = false; m_bStartPage = false; m_pCurrentFont = NULL; m_pCurrentPSFont = NULL; if(m_vecEncSymbol.getItemCount()>0) m_vecEncSymbol.clear(); if(m_vecEncDingbats.getItemCount()>0) m_vecEncDingbats.clear(); m_cs = GR_Graphics::GR_COLORSPACE_COLOR; m_currentColor.m_red = 0; m_currentColor.m_grn = 0; m_currentColor.m_blu = 0; // // Now I need to load in the translations to unicode for Dingbats and Symbols. // loadUnicodeData(); } bool XAP_UnixGnomePrintGraphics::loadUnicodeData(void) { UT_String SymbolName(XAP_App::getApp()->getAbiSuiteLibDir()); SymbolName += "/fonts/symbol.e2u"; char * szName = const_cast(SymbolName.c_str()); FILE * ef = fopen(szName, "r"); char buff[128]; UT_sint32 i; UT_uint32 code,unicode; if(!ef) { UT_DEBUGMSG(("Cannot load Symbol Unicode value file \n")); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return false; } else { // // Load the file //skip comments and empty lines while(fgets(buff,128,ef)) if((*buff != '#')&&(*buff != '\n')) break; UT_sint32 nLines = atoi(buff); for(i=0; i< nLines;i++) { if(!fgets(buff,128,ef)) { UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncSymbol); UT_DEBUGMSG(("Invalid Unicode translation file %s \n",szName)); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); fclose(ef); return false; } if((*buff != '#')&&(*buff != '\n')) { buff[strlen(buff)-1]= 0; //remove '\n' xxx_UT_DEBUGMSG(("Reading line %s \n",buff)); char * comma = strchr(buff, ','); if(!comma) { UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncSymbol); UT_DEBUGMSG(("Invalid Unicode translation file %s \n",szName)); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); fclose(ef); return false; } *comma = 0; sscanf(comma + 1, "%x", &unicode); sscanf(buff,"%x",&code); _encUnicode * p = new _encUnicode; p->fontcode = code; p->unicode = unicode; m_vecEncSymbol.addItem((void *) p); } } fclose(ef); } // // Load the Dingbat encoding file // SymbolName = XAP_App::getApp()->getAbiSuiteLibDir(); SymbolName += "/fonts/dingbats.e2u"; szName = const_cast(SymbolName.c_str()); ef = fopen(szName, "r"); if(!ef) { UT_DEBUGMSG(("Cannot load Dingbats Unicode value file %s \n",szName)); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return false; } else { // // Load the file //skip comments and empty lines while(fgets(buff,128,ef)) if((*buff != '#')&&(*buff != '\n')) break; UT_sint32 nLines = atoi(buff); for(i=0; i< nLines;i++) { if(!fgets(buff,128,ef)) { UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncDingbats); UT_DEBUGMSG(("Invalid Unicode translation file %s \n",szName)); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); fclose(ef); return false; } if((*buff != '#')&&(*buff != '\n')) { buff[strlen(buff)-1]= 0; //remove '\n' xxx_UT_DEBUGMSG(("Reading line %s \n",buff)); char * comma = strchr(buff, ','); if(!comma) { UT_VECTOR_PURGEALL(_encUnicode *, m_vecEncDingbats); UT_DEBUGMSG(("Invalid Unicode translation file %s \n",szName)); UT_ASSERT(UT_SHOULD_NOT_HAPPEN); fclose(ef); return false; } *comma = 0; sscanf(comma + 1, "%x", &unicode); sscanf(buff,"%x",&code); _encUnicode * p = new _encUnicode; p->fontcode = code; p->unicode = unicode; m_vecEncDingbats.addItem((void *) p); } } fclose(ef); } m_vecEncSymbol.qsort(compareCodes); m_vecEncDingbats.qsort(compareCodes); return true; } UT_uint32 XAP_UnixGnomePrintGraphics::getUnicodeForSymbol(UT_uint32 code) { // // Do a binary search later // UT_sint32 nCode = m_vecEncSymbol.getItemCount(); _encUnicode *p = NULL; UT_sint32 i; for(i=0; i< nCode; i++) { p = static_cast<_encUnicode *>( m_vecEncSymbol.getNthItem(i)); if(p->fontcode == code) break; } if(nCode == i || p->fontcode != code) return 0; return p->unicode; } UT_uint32 XAP_UnixGnomePrintGraphics::getUnicodeForDingbats(UT_uint32 code) { // // Do a binary search later // UT_sint32 nCode = m_vecEncSymbol.getItemCount(); _encUnicode *p = NULL; UT_sint32 i; for(i=0; i< nCode; i++) { p = static_cast<_encUnicode *>( m_vecEncDingbats.getNthItem(i)); if(p->fontcode >= code) break; } if(i == nCode || p->fontcode != code) return 0; return p->unicode; } UT_uint32 XAP_UnixGnomePrintGraphics::measureUnRemappedChar(const UT_UCSChar c) { UT_uint32 width = 0; UT_ASSERT(m_pCurrentFont); UT_UCSChar cc = c; // // If the font is in cache we're doing layout calculations so use exactly // the same calculations as the screen uses. // XAP_UnixFont * pUFont = m_pCurrentPSFont->getUnixFont(); UT_sint32 iSize = m_pCurrentPSFont->getSize(); xxx_UT_DEBUGMSG(("SEVIOR: Gnome Looking for font of size %d in the cache \n",iSize)); if(pUFont->isSizeInCache(iSize)) { XAP_UnixFontHandle * pHndl = new XAP_UnixFontHandle(pUFont, iSize); GdkFont* font = pHndl->getGdkFont(); gchar gc = (gchar) c; width = gdk_text_width(font, (gchar*)&gc, 1); delete pHndl; xxx_UT_DEBUGMSG(("SEVIOR: Got Width %d from gdk_font \n",width)); return width; } else { width = (UT_uint32) ((double) m_pCurrentPSFont->getCharWidth(cc) * (double) m_pCurrentPSFont->getSize() / 1000.); xxx_UT_DEBUGMSG(("SEVIOR: Got Width %d from PS font \n",width)); } return width; } void XAP_UnixGnomePrintGraphics::drawChars(const UT_UCSChar* pChars, int iCharOffset, int iLength, UT_sint32 xoff, UT_sint32 yoff) { UT_ASSERT(m_pCurrentFont); // The GR classes are expected to take yoff as the upper-left of // each glyph. PostScript interprets the yoff as the baseline, // which doesn't match this expectation. Adding the ascent of the // font will bring it back to the correct position. yoff += getFontAscent(); // unsigned buffer holds Latin-1 data to character code 255 guchar buf[OUR_LINE_LIMIT*6]; guchar * pD; const UT_UCSChar * pS; const UT_UCSChar * pEnd; xxx_UT_DEBUGMSG(("DOM: drawChars (x: %d) (y: %d)\n", xoff, yoff)); // push a graphics state & save it. then set the font gnome_print_gsave ( m_gpc ) ; gnome_print_setfont (m_gpc, m_pCurrentFont); gnome_print_moveto(m_gpc, _scale_x_dir(xoff), _scale_y_dir(yoff)); pEnd = pChars + iCharOffset + iLength; for (pS = pChars + iCharOffset; pS < pEnd; pS += OUR_LINE_LIMIT) { const UT_UCSChar * pB = 0; pD = buf; for (pB = pS; (pB < pS + OUR_LINE_LIMIT) && (pB < pEnd); pB++) { UT_UCSChar currentChar = *pB; // normal, default case if(m_bisSymbol) { // // Convert to Unicode.. // //currentChar = remapGlyph(*pB, *pB >= 256 ? true : false); currentChar = (UT_UCSChar) getUnicodeForSymbol((UT_uint32) currentChar); } else if(m_bisDingbats) { // // Convert to Unicode.. // //currentChar = remapGlyph(*pB, *pB >= 256 ? true : false); currentChar = (UT_UCSChar) getUnicodeForDingbats((UT_uint32) currentChar); } pD += unichar_to_utf8 (currentChar, pD); } gnome_print_show_sized (m_gpc, (gchar *) buf, pD - buf); } // pop the graphics state gnome_print_grestore ( m_gpc ) ; } void XAP_UnixGnomePrintGraphics::drawLine(UT_sint32 x1, UT_sint32 y1, UT_sint32 x2, UT_sint32 y2) { gnome_print_setlinewidth(m_gpc, m_dLineWidth); gnome_print_moveto(m_gpc, _scale_x_dir(x1), _scale_y_dir(y1)); gnome_print_lineto(m_gpc, _scale_x_dir(x2), _scale_y_dir(y2)); gnome_print_stroke(m_gpc); /* Dom: you don't wanna close the path, you only need to stroke it [ hhhuu hhuiuuu hhuu. Hey beavis, yes said "stroke it" ]*/ } void XAP_UnixGnomePrintGraphics::setFont(GR_Font* pFont) { UT_ASSERT(pFont); // // Need this psFont to get the scales correct // PSFont * psFont = (static_cast (pFont)); m_pCurrentPSFont = psFont; // // We have to see if we must do fancy encoding to unicode for gnomeprint // UT_String pszFname(psFont->getUnixFont()->getName()); UT_sint32 i; for(i=0; pszFname[i] != 0; i++) { pszFname[i] = tolower(pszFname[i]); } if(strstr(pszFname.c_str(),"symbol") != 0) { m_bisSymbol = true; } else if (strstr(pszFname.c_str(),"dingbats") !=0 ) { m_bisDingbats = true; } else { m_bisSymbol = false; m_bisDingbats = false; } // TODO: We *must* be smarter about this, maybe a hash // TODO: of PSFonts -> GnomeFonts if(m_pCurrentFont && GNOME_IS_FONT(m_pCurrentFont)) gnome_font_unref(m_pCurrentFont); m_pCurrentFont = _allocGnomeFont(psFont); // we delay gnome_print_setfont until we draw characters. this fixes // a bug with regard to font sizes < 10 pts in gnome-print version // <= 0.35 at the cost of a slightly larger PS output file } bool XAP_UnixGnomePrintGraphics::queryProperties(GR_Graphics::Properties gp) const { switch (gp) { case DGP_SCREEN: case DGP_OPAQUEOVERLAY: return false; case DGP_PAPER: return true; default: UT_ASSERT(0); return false; } } void XAP_UnixGnomePrintGraphics::setColor(const UT_RGBColor& clr) { if (clr.m_red == m_currentColor.m_red && clr.m_grn == m_currentColor.m_grn && clr.m_blu == m_currentColor.m_blu) return; // NOTE : we always set our color to something RGB, even if the color // NOTE : space is b&w or grayscale m_currentColor.m_red = clr.m_red; m_currentColor.m_grn = clr.m_grn; m_currentColor.m_blu = clr.m_blu; xxx_UT_DEBUGMSG(("Dom: setColor\n")); double red = (double)m_currentColor.m_red / 255.0; double green = (double)m_currentColor.m_grn / 255.0; double blue = (double)m_currentColor.m_blu / 255.0; UT_DEBUGMSG(("SEVIOR: Current red = %f Current green = %f current blue =%f \n",red,green,blue)); gint ret = gnome_print_setrgbcolor(m_gpc,red,green,blue); UT_DEBUGMSG(("SEVIOR: Return value from set = %d \n",ret)); } void XAP_UnixGnomePrintGraphics::setLineWidth(UT_sint32 iLineWidth) { m_dLineWidth = (double)((double)iLineWidth * _scale_factor_get()); } bool XAP_UnixGnomePrintGraphics::startPrint(void) { UT_ASSERT(!m_bStartPrint); m_bStartPrint = true; return _startDocument(); } bool XAP_UnixGnomePrintGraphics::startPage(const char * szPageLabel) { if (m_bStartPage) _endPage(); m_bStartPage = true; m_bNeedStroked = false; return _startPage(szPageLabel); } bool XAP_UnixGnomePrintGraphics::startPage (const char *szPageLabel, UT_uint32, bool, UT_uint32, UT_uint32) { return startPage(szPageLabel); } bool XAP_UnixGnomePrintGraphics::endPrint() { if (m_bStartPage) _endPage(); return _endDocument(); } void XAP_UnixGnomePrintGraphics::setColorSpace(GR_Graphics::ColorSpace c) { m_cs = c; } GR_Graphics::ColorSpace XAP_UnixGnomePrintGraphics::getColorSpace(void) const { return m_cs; } void XAP_UnixGnomePrintGraphics::drawAnyImage (GR_Image* pImg, UT_sint32 xDest, UT_sint32 yDest, bool rgb) { // // One might think that I would have to adjust these sizes because of the // scaling by a factor of 36 for print images. Actually I don't think I do. // gnome-print scales all images to fit in whatever sized piece of screen/paper // you've got. // UT_sint32 iDestWidth = pImg->getDisplayWidth(); UT_sint32 iDestHeight = pImg->getDisplayHeight(); UT_DEBUGMSG(("SEVIOR: Draw any image iDestWidth %d iDestHeight %d \n",iDestWidth,iDestHeight)); GR_UnixGnomeImage * pImage = static_cast(pImg); GdkPixbuf * image = pImage->getData(); UT_ASSERT(image); gnome_print_gsave(m_gpc); gnome_print_translate(m_gpc, _scale_x_dir(xDest), _scale_y_dir(yDest + iDestHeight)); gnome_print_scale(m_gpc, ((double) iDestWidth) * _scale_factor_get (), ((double) iDestHeight) * _scale_factor_get ()); gnome_print_pixbuf (m_gpc, image); gnome_print_grestore(m_gpc); } void XAP_UnixGnomePrintGraphics::drawImage(GR_Image* pImg, UT_sint32 xDest, UT_sint32 yDest) { UT_DEBUGMSG(("SEVIOR: drawing image in gnome-print image type = %d \n", pImg->getType())); if (pImg->getType() != GR_Image::GRT_Raster) { UT_DEBUGMSG(("SEVIOR: Rendering non-raster image in gnome-print \n")); pImg->render(this, xDest, yDest); return; } UT_DEBUGMSG(("SEVIOR: drawing raster image in gnome-print \n")); switch(m_cs) { case GR_Graphics::GR_COLORSPACE_COLOR: drawAnyImage(pImg, xDest, yDest, true); break; case GR_Graphics::GR_COLORSPACE_GRAYSCALE: drawAnyImage(pImg, xDest, yDest, false); break; case GR_Graphics::GR_COLORSPACE_BW: drawAnyImage(pImg, xDest, yDest, false); break; default: UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } } GR_Image* XAP_UnixGnomePrintGraphics::createNewImage(const char* pszName, const UT_ByteBuf* pBB, UT_sint32 iDisplayWidth, UT_sint32 iDisplayHeight, GR_Image::GRType iType) { GR_Image* pImg = NULL; if (iType == GR_Image::GRT_Raster) pImg = new GR_UnixGnomeImage(pszName,iType,true); else if (iType == GR_Image::GRT_Vector) pImg = new GR_VectorImage(pszName); pImg->convertFromBuffer(pBB, iDisplayWidth, iDisplayHeight); return pImg; } /***********************************************************************/ /* Protected things */ /***********************************************************************/ bool XAP_UnixGnomePrintGraphics::_startDocument(void) { return true; } bool XAP_UnixGnomePrintGraphics::_startPage(const char * szPageLabel) { if ( !m_gpm ) return true ; gnome_print_beginpage(m_gpc, szPageLabel); _setup_rotation (); return true; } bool XAP_UnixGnomePrintGraphics::_endPage(void) { if(m_bNeedStroked) gnome_print_stroke(m_gpc); if ( !m_gpm ) return true ; gnome_print_showpage(m_gpc); return true; } bool XAP_UnixGnomePrintGraphics::_endDocument(void) { // bonobo version, we'd don't own the context // or the master, just return if(!m_gpm) return true; gnome_print_master_close(m_gpm); if(!m_bIsPreview) { gnome_print_master_print(m_gpm); } else { GnomePrintMasterPreview *preview; const XAP_StringSet * pSS = m_pApp->getStringSet(); preview = gnome_print_master_preview_new_with_orientation (m_gpm, pSS->getValue(XAP_STRING_ID_DLG_UP_PrintPreviewTitle), !isPortrait()); gtk_widget_show(GTK_WIDGET(preview)); } gtk_object_unref(GTK_OBJECT(m_gpm)); return true; } UT_uint32 XAP_UnixGnomePrintGraphics::_getResolution(void) const { return GPG_RESOLUTION; } void XAP_UnixGnomePrintGraphics::fillRect(UT_RGBColor& c, UT_sint32 x, UT_sint32 y, UT_sint32 w, UT_sint32 h) { // draw background color gnome_print_setrgbcolor(m_gpc, ((double) c.m_red) / 255.0, ((double) c.m_grn) / 255.0, ((double) c.m_blu) / 255.0); gnome_print_newpath (m_gpc); gnome_print_moveto (m_gpc, _scale_x_dir(x), _scale_y_dir(y)); gnome_print_lineto (m_gpc, _scale_x_dir(x+w), _scale_y_dir(y)); gnome_print_lineto (m_gpc, _scale_x_dir(x+w), _scale_y_dir(y+h)); gnome_print_lineto (m_gpc, _scale_x_dir(x), _scale_y_dir(y+h)); gnome_print_lineto (m_gpc, _scale_x_dir(x), _scale_y_dir(y)); gnome_print_closepath (m_gpc); gnome_print_fill (m_gpc); // reset color to its original state gnome_print_setrgbcolor(m_gpc, (int)(m_currentColor.m_red / 255), (int)(m_currentColor.m_grn / 255), (int)(m_currentColor.m_blu / 255)); } void XAP_UnixGnomePrintGraphics::fillRect(UT_RGBColor& c, UT_Rect & r) { fillRect(c, r.left, r.top, r.width, r.height); } void XAP_UnixGnomePrintGraphics::setClipRect(const UT_Rect* pRect) { // TODO: gnome_print_clip() // useful for clipping images and other objects } /***********************************************************************/ /* Things that souldn't happen */ /***********************************************************************/ void XAP_UnixGnomePrintGraphics::setCursor(GR_Graphics::Cursor) { // nada } GR_Graphics::Cursor XAP_UnixGnomePrintGraphics::getCursor(void) const { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return GR_CURSOR_INVALID; } void XAP_UnixGnomePrintGraphics::xorLine(UT_sint32, UT_sint32, UT_sint32, UT_sint32) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::polyLine(UT_Point * /* pts */, UT_uint32 /* nPoints */) { // only used by us for printing red squiggly lines // in the spell-checker UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::invertRect(const UT_Rect* /*pRect*/) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::clearArea(UT_sint32 /*x*/, UT_sint32 /*y*/, UT_sint32 /*width*/, UT_sint32 /*height*/) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::scroll(UT_sint32, UT_sint32) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::scroll(UT_sint32 /* x_dest */, UT_sint32 /* y_dest */, UT_sint32 /* x_src */, UT_sint32 /* y_src */, UT_sint32 /* width */, UT_sint32 /* height */) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } UT_RGBColor * XAP_UnixGnomePrintGraphics::getColor3D(GR_Color3D /*c*/) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return NULL; } void XAP_UnixGnomePrintGraphics::setColor3D(GR_Color3D /*c*/) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } GR_Font* XAP_UnixGnomePrintGraphics::getGUIFont() { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return NULL; } void XAP_UnixGnomePrintGraphics::fillRect(GR_Color3D c, UT_sint32 x, UT_sint32 y, UT_sint32 w, UT_sint32 h) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } void XAP_UnixGnomePrintGraphics::fillRect(GR_Color3D c, UT_Rect &r) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } /***********************************************************************/ /* Done */ /***********************************************************************/ // // This code will return the identical size to that used for the layout // UT_uint32 XAP_UnixGnomePrintGraphics::getFontAscent(GR_Font *fnt) { UT_uint32 asc; #if 0 GnomeFont * gfnt = _allocGnomeFont(static_cast(fnt)); const GnomeFontFace *face; const ArtDRect *bbox; face = gnome_font_get_face (gfnt); bbox = gnome_font_face_get_stdbbox (face); asc = (gint) (bbox->y1 * gnome_font_get_size (gfnt) / 10); gnome_font_unref (gfnt); #endif PSFont * psfnt = static_cast(fnt); XAP_UnixFont * pUFont = psfnt->getUnixFont(); UT_sint32 iSize = psfnt->getSize(); if(pUFont->isSizeInCache(iSize)) { XAP_UnixFontHandle * pHndl = new XAP_UnixFontHandle(pUFont, iSize); GdkFont* pFont = pHndl->getGdkFont(); GdkFont* pMatchFont=pHndl->getMatchGdkFont(); asc = MAX(pFont->ascent, pMatchFont->ascent); delete pHndl; } else { GlobalFontInfo * gfi = psfnt->getMetricsData()->gfi; UT_ASSERT(gfi); asc = (UT_uint32) ( (double) gfi->fontBBox.ury * (double) psfnt->getSize() /1000.); } return asc; } /* This function does not expect in return the font ascent, it expects the font bbox.ury. Chema */ UT_uint32 XAP_UnixGnomePrintGraphics::getFontAscent() { UT_uint32 asc; asc = getFontAscent(static_cast(m_pCurrentPSFont)); return asc; } UT_uint32 XAP_UnixGnomePrintGraphics::getFontDescent(GR_Font *fnt) { UT_uint32 des; #if 0 GnomeFont * gfnt = _allocGnomeFont(static_cast(fnt)); const GnomeFontFace *face; const ArtDRect *bbox; face = gnome_font_get_face (gfnt); bbox = gnome_font_face_get_stdbbox (face); des = (gint) (bbox->y0 * gnome_font_get_size (gfnt) / 10); des *= -1; gnome_font_unref (gfnt); #endif PSFont * psfnt = static_cast(fnt); XAP_UnixFont * pUFont = psfnt->getUnixFont(); UT_sint32 iSize = psfnt->getSize(); if(pUFont->isSizeInCache(iSize)) { XAP_UnixFontHandle * pHndl = new XAP_UnixFontHandle(pUFont, iSize); GdkFont* pFont = pHndl->getGdkFont(); GdkFont* pMatchFont=pHndl->getMatchGdkFont(); des = MAX(pFont->descent, pMatchFont->descent); delete pHndl; } else { GlobalFontInfo * gfi = psfnt->getMetricsData()->gfi; UT_ASSERT(gfi); des = (UT_uint32) ((double) -(gfi->fontBBox.lly) * (double) psfnt->getSize() / 1000.); } return des; return des; } UT_uint32 XAP_UnixGnomePrintGraphics::getFontDescent() { UT_uint32 des; #if 0 const GnomeFontFace *face; const ArtDRect *bbox; GnomeFont *font; font = m_pCurrentFont; UT_ASSERT(GNOME_IS_FONT (font)); face = gnome_font_get_face (font); UT_ASSERT(GNOME_IS_FONT_FACE (face)); bbox = gnome_font_face_get_stdbbox (face); des = (gint) (bbox->y0 * gnome_font_get_size (font) / 10); des *= -1; #endif des = getFontDescent(static_cast(m_pCurrentPSFont)); return des; } UT_uint32 XAP_UnixGnomePrintGraphics::getFontHeight() { UT_ASSERT(m_pCurrentFont); UT_sint32 height = getFontAscent() + getFontDescent(); return height; } UT_uint32 XAP_UnixGnomePrintGraphics::getFontHeight(GR_Font *fnt) { UT_sint32 height = getFontAscent(fnt) + getFontDescent(fnt); return height; } GR_Font* XAP_UnixGnomePrintGraphics::findFont(const char* pszFontFamily, const char* pszFontStyle, const char* /* pszFontVariant */, const char* pszFontWeight, const char* /* pszFontStretch */, const char* pszFontSize) { UT_ASSERT(pszFontFamily); UT_ASSERT(pszFontStyle); UT_ASSERT(pszFontWeight); UT_ASSERT(pszFontSize); // convert styles to XAP_UnixFont:: formats XAP_UnixFont::style s = XAP_UnixFont::STYLE_NORMAL; // this is kind of sloppy if (!UT_strcmp(pszFontStyle, "normal") && !UT_strcmp(pszFontWeight, "normal")) { s = XAP_UnixFont::STYLE_NORMAL; } else if (!UT_strcmp(pszFontStyle, "normal") && !UT_strcmp(pszFontWeight, "bold")) { s = XAP_UnixFont::STYLE_BOLD; } else if (!UT_strcmp(pszFontStyle, "italic") && !UT_strcmp(pszFontWeight, "normal")) { s = XAP_UnixFont::STYLE_ITALIC; } else if (!UT_strcmp(pszFontStyle, "italic") && !UT_strcmp(pszFontWeight, "bold")) { s = XAP_UnixFont::STYLE_BOLD_ITALIC; } else { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); } // Request the appropriate XAP_UnixFont::, and bury it in an // instance of a UnixFont:: with the correct size. XAP_UnixFont * unixfont = m_fm->getFont(pszFontFamily, s); XAP_UnixFontHandle * item = NULL; // // This piece of code scales the FONT chosen at low resolution to that at high // resolution. This fixes bug 1632 and other non-WYSIWYG behaviour. // UT_uint32 iSize = getAppropriateFontSizeFromString(pszFontSize); if (unixfont) { // end up burying a pointer to the unix font, but first we need a handle item = new XAP_UnixFontHandle(unixfont,iSize); } else { // Oops! We don't have that font here. substitute something // we know we have (get smarter about this later) g_print ("Get times new roman !!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); item = new XAP_UnixFontHandle(m_fm->getFont("Times New Roman", s),iSize); } xxx_UT_DEBUGMSG(("Using Gnome-Print PS Font Size %d \n",iSize)); PSFont * pFont = new PSFont(item->getUnixFont(), iSize); delete item; UT_ASSERT(pFont); return pFont; } /***********************************************************************/ /* Private Scaling Conversion Routines */ /***********************************************************************/ void XAP_UnixGnomePrintGraphics::_setup_rotation (void) { double affine [6]; // do nothing for this default case if (isPortrait ()) return; // we have to apply an affine to the print context for // each page in order to print in landscape mode art_affine_rotate (affine, 90.0); gnome_print_concat (m_gpc, affine); art_affine_translate (affine, 0, - _get_height ()); gnome_print_concat (m_gpc, affine); } double XAP_UnixGnomePrintGraphics::_scale_factor_get (void) { return ((double) 72.0 / (double) GPG_RESOLUTION); } double XAP_UnixGnomePrintGraphics::_scale_factor_get_inverse (void) { return ((double) GPG_RESOLUTION / (double) 72.0); } double XAP_UnixGnomePrintGraphics::_scale_x_dir (int x) { double d = 0.0; d = (double) x; d *= _scale_factor_get (); return d; } double XAP_UnixGnomePrintGraphics::_get_height (void) { if (m_paper) { if (isPortrait ()) return gnome_paper_psheight (m_paper); else return gnome_paper_pswidth (m_paper); } else { /* FIXME: Hardcode US-Letter values as a standby/fallback for now */ if (isPortrait ()) return 11.0; else return 8.5; } } double XAP_UnixGnomePrintGraphics::_scale_y_dir (int y) { double d = 0.0; double page_length = 0.0; page_length = _get_height (); /* This one is obscure: * Our drawChars and drawLine functions recieve yDests relative to the * page that they're on. drawImg doesn't. We need to properly * correct for that */ #if 0 d = page_length - (double) y; d *= _scale_factor_get(); #else d = page_length - (double)((int)(y * _scale_factor_get()) % (int)page_length); #endif return d; }