/* AbiSource Application Framework * Copyright (C) 1998 AbiSource, Inc. * Copyright (C) 2009 Hubert Figuiere * * 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 "ut_string.h" #include "ut_debugmsg.h" #include "xap_Dlg_FontChooser.h" #include "ut_string_class.h" #include "gr_Graphics.h" #include "gr_Painter.h" /*****************************************************************/ // your typographer's standard nonsense latin font phrase #define PREVIEW_ENTRY_DEFAULT_STRING "Lorem ipsum dolor sit amet, consectetaur adipisicing..." XAP_Dialog_FontChooser::XAP_Dialog_FontChooser(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) : XAP_Dialog_NonPersistent(pDlgFactory,id, "interface/dialogfont") { m_answer = a_CANCEL; m_pGraphics = NULL; m_pFontPreview = NULL; m_bUnderline = false; m_bOverline = false; m_bStrikeout = false; m_bTopline = false; m_bBottomline = false; m_bHidden = false; m_bSuperScript = false; m_bSubScript = false; m_bChangedFontFamily = false; m_bChangedTextTransform = false; m_bChangedFontSize = false; m_bChangedFontWeight = false; m_bChangedFontStyle = false; m_bChangedColor = false; m_bChangedBGColor = false; m_bChangedUnderline = false; m_bChangedOverline = false; m_bChangedStrikeOut = false; m_bChangedTopline = false; m_bChangedBottomline = false; m_bChangedHidden = false; m_bChangedSuperScript = false; m_bChangedSubScript = false; UT_UCS4_cloneString_char (&m_drawString, PREVIEW_ENTRY_DEFAULT_STRING); } XAP_Dialog_FontChooser::~XAP_Dialog_FontChooser(void) { FREEP(m_drawString); DELETEP(m_pFontPreview); } void XAP_Dialog_FontChooser::setDrawString(const UT_UCSChar * str) { FREEP(m_drawString); UT_sint32 len = UT_UCS4_strlen(str); if(len <= 0) { UT_UCS4_cloneString_char (&m_drawString, PREVIEW_ENTRY_DEFAULT_STRING); } else { UT_UCS4_cloneString(&m_drawString, str); } } void XAP_Dialog_FontChooser::setGraphicsContext(GR_Graphics * pGraphics) { m_pGraphics = pGraphics; } void XAP_Dialog_FontChooser::_createFontPreviewFromGC(GR_Graphics * gc, UT_uint32 width, UT_uint32 height) { UT_ASSERT(gc); m_pFontPreview = new XAP_Preview_FontPreview(gc,m_sColorBackground.c_str()); UT_return_if_fail(m_pFontPreview); m_pFontPreview->setWindowSize(width, height); m_pFontPreview->setVecProperties( & m_mapProps); } void XAP_Dialog_FontChooser::addOrReplaceVecProp(const std::string & sProp, const std::string & sVal) { m_mapProps[sProp] = sVal; } /*! * This method updates the drawing area in the dialog. */ void XAP_Dialog_FontChooser::event_previewExposed(const UT_UCSChar * pszChars) { UT_UCSChar * pszNew = NULL; if(!pszChars || UT_UCS4_strlen(pszChars) <= 0) { //FREEP(pszChars); // we should not g_free it here UT_UCS4_cloneString_char (&pszNew, PREVIEW_ENTRY_DEFAULT_STRING); if (!pszNew) return; m_pFontPreview->setDrawString(pszNew); } else { m_pFontPreview->setDrawString(pszChars); } m_pFontPreview->draw(); FREEP(pszNew); } /*! * This method clears the drawing area in the dialog. */ void XAP_Dialog_FontChooser::event_previewClear(void) { m_pFontPreview->clearScreen(); } /*! * This method returns a std::string of the const char * value associated with the * the property szProp. Stolen from ap_Dialog_Lists. * It assumes properties and values are stored the array like this: * vecProp(n) : vecProp(n+1) * "property" : "value" */ const std::string XAP_Dialog_FontChooser::getVal(const std::string & sProp) const { PropMap::const_iterator iter = m_mapProps.find(sProp); if(iter == m_mapProps.end()) { return ""; } return iter->second; } /*! * This method sets all the local properties from a vector of pointers * to const gchar * strings of Property - Value pairs. * This method wipes out all the old values and clears all the bools * assciated with them. */ void XAP_Dialog_FontChooser::setAllPropsFromVec(const UT_Vector & vProps) { UT_sint32 remCount = vProps.getItemCount(); if(remCount <= 0) return; // BAD BAD, we have wrong count UT_ASSERT_HARMLESS(remCount % 2 == 0); if(remCount % 2) { remCount--; } m_mapProps.clear(); UT_sint32 i = 0; for(i=0; i< remCount; i+=2) { m_mapProps.insert(std::make_pair((const char*)vProps.getNthItem(i), (const char*)vProps.getNthItem(i+1))); } // // Do the Text decorations // const std::string sDecor = getVal("text-decoration"); m_bUnderline = (NULL != strstr(sDecor.c_str(),"underline")); m_bOverline = (NULL != strstr(sDecor.c_str(),"overline")); m_bStrikeout = (NULL != strstr(sDecor.c_str(),"line-through")); m_bTopline = (NULL != strstr(sDecor.c_str(),"topline")); m_bBottomline = (NULL != strstr(sDecor.c_str(),"bottomline")); const std::string sDisplay = getVal("display"); m_bHidden = !strcmp(sDisplay.c_str(),"none"); const std::string sPosition = getVal("text-position"); m_bSuperScript = strcmp(sPosition.c_str(),"superscript")==0; m_bSubScript = strcmp(sPosition.c_str(),"subscript")==0; } void XAP_Dialog_FontChooser::setFontFamily(const std::string& sFontFamily) { m_sFontFamily = sFontFamily; addOrReplaceVecProp("font-family",sFontFamily); } void XAP_Dialog_FontChooser::setTextTransform(const std::string& sTextTransform) { m_sTextTransform = sTextTransform; addOrReplaceVecProp("text-transform",sTextTransform); } void XAP_Dialog_FontChooser::setFontSize(const std::string& sFontSize) { m_sFontSize = sFontSize; addOrReplaceVecProp("font-size",sFontSize); } void XAP_Dialog_FontChooser::setFontWeight(const std::string& sFontWeight) { m_sFontWeight = sFontWeight; addOrReplaceVecProp("font-weight",sFontWeight); } void XAP_Dialog_FontChooser::setFontStyle(const std::string& sFontStyle) { m_sFontStyle = sFontStyle; addOrReplaceVecProp("font-style",sFontStyle); } void XAP_Dialog_FontChooser::setColor(const std::string& sColor) { m_sColor = sColor; addOrReplaceVecProp("color",sColor); } void XAP_Dialog_FontChooser::setBGColor(const std::string& sBGColor) { m_sBGColor = sBGColor; addOrReplaceVecProp("bgcolor",sBGColor); } void XAP_Dialog_FontChooser::setSuperScript(bool bSuperScript) { static char none[] = "superscript"; static char empty[] = ""; if(bSuperScript) { addOrReplaceVecProp("text-position",none); } else { addOrReplaceVecProp("text-position",empty); } m_bSuperScript = bSuperScript; } void XAP_Dialog_FontChooser::setSubScript(bool bSubScript) { static char none[] = "subscript"; static char empty[] = ""; if(bSubScript) { addOrReplaceVecProp("text-position",none); } else { addOrReplaceVecProp("text-position",empty); } m_bSubScript = bSubScript; } void XAP_Dialog_FontChooser::setHidden(bool bHidden) { static char none[] = "none"; static char empty[] = ""; if(bHidden) { addOrReplaceVecProp("display",none); } else { addOrReplaceVecProp("display",empty); } m_bHidden = bHidden; } void XAP_Dialog_FontChooser::setBackGroundColor(const gchar * pBackground) { m_sColorBackground = pBackground; } void XAP_Dialog_FontChooser::setFontDecoration(bool bUnderline, bool bOverline, bool bStrikeOut, bool bTopline, bool bBottomline) { m_bUnderline = bUnderline; m_bOverline = bOverline; m_bStrikeout = bStrikeOut; m_bTopline = bTopline; m_bBottomline = bBottomline; static gchar s[50]; UT_String decors; decors.clear(); if(bUnderline) decors += "underline "; if(bStrikeOut) decors += "line-through "; if(bOverline) decors += "overline "; if(bTopline) decors += "topline "; if(bBottomline) decors += "bottomline "; if(!bUnderline && !bStrikeOut && !bOverline && !bTopline && !bBottomline) decors = "none"; sprintf(s,"%s",decors.c_str()); addOrReplaceVecProp("text-decoration",(const gchar *) s); } XAP_Dialog_FontChooser::tAnswer XAP_Dialog_FontChooser::getAnswer(void) const { return m_answer; } bool XAP_Dialog_FontChooser::getChangedFontFamily(const gchar ** pszFontFamily) const { bool bchanged = didPropChange(m_sFontFamily,getVal("font-family")); bool useVal = (bchanged && !m_bChangedFontFamily); if (pszFontFamily && useVal) *pszFontFamily = getVal("font-family").c_str(); else if(pszFontFamily) *pszFontFamily = m_sFontFamily.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedTextTransform(const gchar ** pszTextTransform) const { bool bchanged = didPropChange(m_sTextTransform,getVal("text-transform")); bool useVal = (bchanged && !m_bChangedTextTransform); if (pszTextTransform && useVal) *pszTextTransform = getVal("text-transform").c_str(); else if(pszTextTransform) *pszTextTransform = m_sTextTransform.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedFontSize(const gchar ** pszFontSize) const { bool bchanged = didPropChange(m_sFontSize,getVal("font-size")); bool useVal = (bchanged && !m_bChangedFontSize); if (pszFontSize && useVal) *pszFontSize = getVal("font-size").c_str(); else if(pszFontSize) *pszFontSize = m_sFontSize.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedFontWeight(const gchar ** pszFontWeight) const { bool bchanged = didPropChange(m_sFontWeight,getVal("font-weight")); bool useVal = (bchanged && !m_bChangedFontWeight); if (pszFontWeight && useVal) *pszFontWeight = getVal("font-weight").c_str(); else if(pszFontWeight) *pszFontWeight = m_sFontWeight.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedFontStyle(const gchar ** pszFontStyle) const { bool bchanged = didPropChange(m_sFontStyle,getVal("font-style")); bool useVal = (bchanged && !m_bChangedFontStyle); if (pszFontStyle && useVal) *pszFontStyle = getVal("font-style").c_str(); else if(pszFontStyle) *pszFontStyle = m_sFontStyle.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedBGColor(const gchar ** pszBGColor) const { bool bchanged = didPropChange(m_sBGColor,getVal("bgcolor")); bool useVal = (bchanged && !m_bChangedBGColor); if (pszBGColor && useVal) *pszBGColor = getVal("bgcolor").c_str(); else if(pszBGColor) *pszBGColor = m_sBGColor.c_str(); return bchanged; } bool XAP_Dialog_FontChooser::getChangedColor(const gchar ** pszColor) const { bool bchanged = didPropChange(m_sColor,getVal("color")); bool useVal = (bchanged && !m_bChangedColor); if (pszColor && useVal) *pszColor = getVal("color").c_str(); else if(pszColor) *pszColor = m_sColor.c_str(); return bchanged; } /*! * Compare two prop values and gracefully handle the cases of NULL pointers */ bool XAP_Dialog_FontChooser::didPropChange(const std::string & v1, const std::string & v2) const { if(v1.empty() && v2.empty()) return false; else if(v1.empty() || v2.empty()) return true; return v1 != v2; } bool XAP_Dialog_FontChooser::getChangedHidden(bool * pbHidden) const { if (pbHidden) *pbHidden = m_bHidden; return m_bChangedHidden; } bool XAP_Dialog_FontChooser::getChangedSuperScript(bool * pbSuperScript) const { if (pbSuperScript) *pbSuperScript = m_bSuperScript; return m_bChangedSuperScript; } bool XAP_Dialog_FontChooser::getChangedSubScript(bool * pbSubScript) const { if (pbSubScript) *pbSubScript = m_bSubScript; return m_bChangedSubScript; } bool XAP_Dialog_FontChooser::getChangedUnderline(bool * pbUnderline) const { if (pbUnderline) *pbUnderline = m_bUnderline; return m_bChangedUnderline; } bool XAP_Dialog_FontChooser::getChangedOverline(bool * pbOverline) const { if (pbOverline) *pbOverline = m_bOverline; return m_bChangedOverline; } bool XAP_Dialog_FontChooser::getChangedStrikeOut(bool * pbStrikeOut) const { if (pbStrikeOut) *pbStrikeOut = m_bStrikeout; return m_bChangedStrikeOut; } bool XAP_Dialog_FontChooser::getChangedTopline(bool * pbTopline) const { if (pbTopline) *pbTopline = m_bTopline; return m_bChangedTopline; } bool XAP_Dialog_FontChooser::getChangedBottomline(bool * pbBottomline) const { if (pbBottomline) *pbBottomline = m_bBottomline; return m_bChangedBottomline; } ///////////////////////////////////////////////////////////////////////// XAP_Preview_FontPreview::XAP_Preview_FontPreview(GR_Graphics * gc, const gchar * pszClrBackground) : XAP_Preview(gc), m_pFont(NULL), m_iAscent(0), m_iDescent(0), m_iHeight(0) { if(pszClrBackground != NULL && strcmp(pszClrBackground,"transparent")!=0) UT_parseColor(pszClrBackground,m_clrBackground); else UT_setColor(m_clrBackground,255,255,255); } XAP_Preview_FontPreview::~XAP_Preview_FontPreview() { } /*! * This method assigns a pointer to a * vector with Char * strings of span-level properties * The vector has const gchar * string in the order * (n) Property (n+1) Value * * This code stolen from ap_Dialog_Lists.cpp */ void XAP_Preview_FontPreview::setVecProperties( const XAP_Dialog_FontChooser::PropMap * vFontProps) { m_mapProps = vFontProps; } /*! * This method returns a pointer to the const char * value associated with the * the property szProp. Stolen from ap_Dialog_Lists. */ const std::string XAP_Preview_FontPreview::getVal(const std::string & sProp) { XAP_Dialog_FontChooser::PropMap::const_iterator iter = m_mapProps->find(sProp); if(iter == m_mapProps->end()) { return ""; } return iter->second; } /* * * Finally draw the characters in the preview. * */ void XAP_Preview_FontPreview::draw(void) { // // Get text decorations. // bool isUnder,isOver,isStrike; const std::string sDecor = getVal("text-decoration"); if(!sDecor.empty()) { isUnder = (NULL != strstr(sDecor.c_str(),"underline")); isOver = (NULL != strstr(sDecor.c_str(),"overline")); isStrike = (NULL != strstr(sDecor.c_str(),"line-through")); } else { isUnder = false; isOver = false; isStrike = false; } // // Do foreground and background colors. // UT_RGBColor FGcolor(0,0,0); const std::string sFGColor = getVal("color"); if(!sFGColor.empty()) UT_parseColor(sFGColor.c_str(),FGcolor); UT_RGBColor BGcolor(m_clrBackground); const std::string sBGColor = getVal("bgcolor"); if(!sBGColor.empty() && strcmp(sBGColor.c_str(),"transparent") != 0) UT_parseColor(sBGColor.c_str(),BGcolor); // // Get the font and bold/italic- ness // //GR_Font * pFont; std::string sFamily = getVal("font-family"); std::string sStyle = getVal("font-style"); std::string sVariant = getVal("font-variant"); std::string sStretch = getVal("font-stretch"); std::string sSize = getVal("font-size"); std::string sWeight = getVal("font-weight"); if(sFamily.empty()) sFamily = "Times New Roman"; if(sStyle.empty()) sStyle = "normal"; if(sVariant.empty()) sVariant = "normal"; if(sStretch.empty()) sStretch = "normal"; if(sSize.empty()) sSize="12pt"; if(sWeight.empty()) sWeight = "normal"; m_pFont = m_gc->findFont(sFamily.c_str(), sStyle.c_str(), sVariant.c_str(), sWeight.c_str(), sStretch.c_str(), sSize.c_str(), NULL); UT_ASSERT_HARMLESS(m_pFont); if(!m_pFont) { clearScreen(); return; } m_gc->setFont(m_pFont); m_iAscent = m_gc->getFontAscent(m_pFont); m_iDescent = m_gc->getFontDescent(m_pFont); m_iHeight = m_gc->getFontHeight(m_pFont); // // Clear the screen! // clearScreen(); // // Calculate the draw coordinates position // UT_sint32 iWinWidth = m_gc->tlu(getWindowWidth()); UT_sint32 iWinHeight = m_gc->tlu(getWindowHeight()); UT_sint32 iTop = (iWinHeight - m_iHeight)/2; UT_sint32 len = UT_UCS4_strlen(m_pszChars); UT_sint32 twidth = m_gc->measureString(m_pszChars,0,len,NULL); UT_sint32 iLeft = (iWinWidth - twidth)/2; // // Fill the background color // GR_Painter painter(m_gc); if(!sBGColor.empty()) painter.fillRect(BGcolor,iLeft,iTop,twidth,m_iHeight); // // Do the draw chars at last! // m_gc->setColor(FGcolor); painter.drawChars(m_pszChars, 0, len, iLeft, iTop); // // Do the decorations // if(isUnder) { UT_sint32 iDrop = iTop + m_iAscent + m_iDescent/3; painter.drawLine(iLeft,iDrop,iLeft+twidth,iDrop); } if(isOver) { UT_sint32 iDrop = iTop + m_gc->tlu(1) + (UT_MAX(m_gc->tlu(10),m_iAscent) - m_gc->tlu(10))/8; painter.drawLine(iLeft,iDrop,iLeft+twidth,iDrop); } if(isStrike) { UT_sint32 iDrop = iTop + m_iAscent * 2 /3; painter.drawLine(iLeft,iDrop,iLeft+twidth,iDrop); } // bad hardcoded color, but this will probably [ <-this assumption is the bad thing :) ] never be different anyway m_gc->setColor(UT_RGBColor(0,0,0)); painter.drawLine(0, 0, m_gc->tlu(getWindowWidth()), 0); painter.drawLine(m_gc->tlu(getWindowWidth()) - m_gc->tlu(1), 0, m_gc->tlu(getWindowWidth()) - m_gc->tlu(1), m_gc->tlu(getWindowHeight())); painter.drawLine(m_gc->tlu(getWindowWidth()) - m_gc->tlu(1), m_gc->tlu(getWindowHeight()) - m_gc->tlu(1), 0, m_gc->tlu(getWindowHeight()) - m_gc->tlu(1)); painter.drawLine(0, m_gc->tlu(getWindowHeight()) - m_gc->tlu(1), 0, 0); } void XAP_Preview_FontPreview::clearScreen(void) { UT_sint32 iWidth = m_gc->tlu(getWindowWidth()); UT_sint32 iHeight = m_gc->tlu(getWindowHeight()); GR_Painter painter(m_gc); // clear the whole drawing area, except for the border painter.fillRect(m_clrBackground, 0 + m_gc->tlu(1), 0 + m_gc->tlu(1), iWidth - m_gc->tlu(2), iHeight - m_gc->tlu(2)); }