fixed rotated text on vertical tab in XFontImp and a rotate function in FontImp interface
This commit is contained in:
parent
1fc16d3d3d
commit
99c92a6373
9 changed files with 419 additions and 52 deletions
25
src/Font.cc
25
src/Font.cc
|
@ -19,7 +19,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
//$Id: Font.cc,v 1.21 2002/11/24 05:23:36 rathnor Exp $
|
//$Id: Font.cc,v 1.22 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
|
|
||||||
#include "Font.hh"
|
#include "Font.hh"
|
||||||
|
@ -69,7 +69,7 @@ bool Font::m_utf8mode = false;
|
||||||
|
|
||||||
Font::Font(const char *name, bool antialias):
|
Font::Font(const char *name, bool antialias):
|
||||||
m_fontimp(0),
|
m_fontimp(0),
|
||||||
m_antialias(false) {
|
m_antialias(false), m_rotated(false) {
|
||||||
|
|
||||||
// MB_CUR_MAX returns the size of a char in the current locale
|
// MB_CUR_MAX returns the size of a char in the current locale
|
||||||
if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
|
if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
|
||||||
|
@ -115,7 +115,7 @@ Font::~Font() {
|
||||||
void Font::setAntialias(bool flag) {
|
void Font::setAntialias(bool flag) {
|
||||||
bool loaded = m_fontimp->loaded();
|
bool loaded = m_fontimp->loaded();
|
||||||
#ifdef USE_XFT
|
#ifdef USE_XFT
|
||||||
if (flag && !isAntialias()) {
|
if (flag && !isAntialias() && !m_rotated) {
|
||||||
m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
|
m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
|
||||||
} else if (!flag && isAntialias())
|
} else if (!flag && isAntialias())
|
||||||
#endif // USE_XFT
|
#endif // USE_XFT
|
||||||
|
@ -164,4 +164,23 @@ void Font::drawText(Drawable w, int screen, GC gc, const char *text, size_t len,
|
||||||
m_fontimp->drawText(w, screen, gc, text, len, x, y);
|
m_fontimp->drawText(w, screen, gc, text, len, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Font::rotate(float angle) {
|
||||||
|
#ifdef USE_XFT
|
||||||
|
// if we are rotated and we are changing to horiz text
|
||||||
|
// and we were antialiased before we rotated then change to XftFontImp
|
||||||
|
if (isRotated() && angle == 0 && isAntialias())
|
||||||
|
m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
|
||||||
|
#endif // USE_XFT
|
||||||
|
// change to a font imp that handles rotated fonts (i.e just XFontImp at the moment)
|
||||||
|
// if we're going to rotate this font
|
||||||
|
if (angle != 0 && isAntialias() && !isRotated()) {
|
||||||
|
m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Note: only XFontImp implements FontImp::rotate
|
||||||
|
m_fontimp->rotate(angle);
|
||||||
|
|
||||||
|
m_rotated = (angle == 0 ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
//$Id: Font.hh,v 1.8 2002/10/19 14:00:37 fluxgen Exp $
|
//$Id: Font.hh,v 1.9 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#ifndef FBTK_FONT_HH
|
#ifndef FBTK_FONT_HH
|
||||||
#define FBTK_FONT_HH
|
#define FBTK_FONT_HH
|
||||||
|
@ -62,8 +62,13 @@ public:
|
||||||
unsigned int height() const;
|
unsigned int height() const;
|
||||||
int ascent() const;
|
int ascent() const;
|
||||||
int descent() const;
|
int descent() const;
|
||||||
|
/**
|
||||||
|
Rotate font in any angle (currently only 90 degrees supported and just XFont implementation)
|
||||||
|
*/
|
||||||
|
void rotate(float angle);
|
||||||
void drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const;
|
void drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const;
|
||||||
bool isAntialias() const { return m_antialias; }
|
bool isAntialias() const { return m_antialias; }
|
||||||
|
bool isRotated() const { return m_rotated; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::auto_ptr<FontImp> m_fontimp;
|
std::auto_ptr<FontImp> m_fontimp;
|
||||||
|
@ -71,6 +76,7 @@ private:
|
||||||
static bool m_multibyte;
|
static bool m_multibyte;
|
||||||
static bool m_utf8mode;
|
static bool m_utf8mode;
|
||||||
bool m_antialias;
|
bool m_antialias;
|
||||||
|
bool m_rotated; ///< wheter we're rotated or not
|
||||||
};
|
};
|
||||||
|
|
||||||
}; //end namespace FbTk
|
}; //end namespace FbTk
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: FontImp.hh,v 1.3 2002/10/19 13:57:48 fluxgen Exp $
|
// $Id: FontImp.hh,v 1.4 2002/11/25 14:07:20 fluxgen Exp $
|
||||||
|
|
||||||
#ifndef FBTK_FONTIMP_HH
|
#ifndef FBTK_FONTIMP_HH
|
||||||
#define FBTK_FONTIMP_HH
|
#define FBTK_FONTIMP_HH
|
||||||
|
@ -35,6 +35,7 @@ namespace FbTk {
|
||||||
/**
|
/**
|
||||||
FontImp, second part of the bridge pattern for fonts
|
FontImp, second part of the bridge pattern for fonts
|
||||||
pure interface class.
|
pure interface class.
|
||||||
|
@see Font
|
||||||
*/
|
*/
|
||||||
class FontImp {
|
class FontImp {
|
||||||
public:
|
public:
|
||||||
|
@ -46,6 +47,7 @@ public:
|
||||||
virtual int descent() const = 0;
|
virtual int descent() const = 0;
|
||||||
virtual unsigned int height() const = 0;
|
virtual unsigned int height() const = 0;
|
||||||
virtual bool loaded() const = 0;
|
virtual bool loaded() const = 0;
|
||||||
|
virtual void rotate(float angle) { } // by default, no rotate support
|
||||||
protected:
|
protected:
|
||||||
FontImp() { }
|
FontImp() { }
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: Screen.cc,v 1.83 2002/11/24 20:56:06 fluxgen Exp $
|
// $Id: Screen.cc,v 1.84 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
|
|
||||||
#include "Screen.hh"
|
#include "Screen.hh"
|
||||||
|
@ -286,6 +286,13 @@ resource(rm, screenname, altscreenname)
|
||||||
image_control, fluxbox->getStyleFilename(), getRootCommand().c_str());
|
image_control, fluxbox->getStyleFilename(), getRootCommand().c_str());
|
||||||
|
|
||||||
theme->reconfigure(*resource.antialias);
|
theme->reconfigure(*resource.antialias);
|
||||||
|
// special case for tab rotated
|
||||||
|
if (*resource.tab_rotate_vertical &&
|
||||||
|
( *resource.tab_placement == Tab::PLEFT || *resource.tab_placement == Tab::PRIGHT)) {
|
||||||
|
theme->getWindowStyle().tab.font.rotate(90);
|
||||||
|
} else {
|
||||||
|
theme->getWindowStyle().tab.font.rotate(0);
|
||||||
|
}
|
||||||
|
|
||||||
const char *s = i18n->getMessage(
|
const char *s = i18n->getMessage(
|
||||||
FBNLS::ScreenSet, FBNLS::ScreenPositionLength,
|
FBNLS::ScreenSet, FBNLS::ScreenPositionLength,
|
||||||
|
@ -504,6 +511,13 @@ void BScreen::reconfigure() {
|
||||||
theme->setRootCommand(getRootCommand());
|
theme->setRootCommand(getRootCommand());
|
||||||
theme->load(Fluxbox::instance()->getStyleFilename());
|
theme->load(Fluxbox::instance()->getStyleFilename());
|
||||||
theme->reconfigure(*resource.antialias);
|
theme->reconfigure(*resource.antialias);
|
||||||
|
// special case for tab rotated
|
||||||
|
if (*resource.tab_rotate_vertical &&
|
||||||
|
( *resource.tab_placement == Tab::PLEFT || *resource.tab_placement == Tab::PRIGHT)) {
|
||||||
|
theme->getWindowStyle().tab.font.rotate(90);
|
||||||
|
} else {
|
||||||
|
theme->getWindowStyle().tab.font.rotate(0);
|
||||||
|
}
|
||||||
|
|
||||||
I18n *i18n = I18n::instance();
|
I18n *i18n = I18n::instance();
|
||||||
|
|
||||||
|
|
44
src/Tab.cc
44
src/Tab.cc
|
@ -19,7 +19,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: Tab.cc,v 1.41 2002/11/17 13:40:01 fluxgen Exp $
|
// $Id: Tab.cc,v 1.42 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#include "Tab.hh"
|
#include "Tab.hh"
|
||||||
|
|
||||||
|
@ -367,43 +367,30 @@ void Tab::draw(bool pressed) const {
|
||||||
GC gc = ((m_win->isFocused()) ? m_win->getScreen()->getWindowStyle()->tab.l_text_focus_gc :
|
GC gc = ((m_win->isFocused()) ? m_win->getScreen()->getWindowStyle()->tab.l_text_focus_gc :
|
||||||
m_win->getScreen()->getWindowStyle()->tab.l_text_unfocus_gc);
|
m_win->getScreen()->getWindowStyle()->tab.l_text_unfocus_gc);
|
||||||
|
|
||||||
// Different routines for drawing rotated text
|
|
||||||
// TODO: rotated font
|
|
||||||
/*if ((m_win->getScreen()->getTabPlacement() == PLEFT ||
|
|
||||||
m_win->getScreen()->getTabPlacement() == PRIGHT) &&
|
|
||||||
(!m_win->isShaded() && m_win->getScreen()->isTabRotateVertical())) {
|
|
||||||
|
|
||||||
tabtext_w = DrawUtil::XRotTextWidth(m_win->getScreen()->getWindowStyle()->tab.rot_font,
|
|
||||||
m_win->getTitle().c_str(), m_win->getTitle().size());
|
|
||||||
tabtext_w += (m_win->frame.bevel_w * 4);
|
|
||||||
|
|
||||||
DrawUtil::DrawRotString(m_display, m_tabwin, gc,
|
|
||||||
m_win->getScreen()->getWindowStyle()->tab.rot_font,
|
|
||||||
m_win->getScreen()->getWindowStyle()->tab.font.justify,
|
|
||||||
tabtext_w, m_size_w, m_size_h,
|
|
||||||
m_win->frame.bevel_w, m_win->getTitle().c_str());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*/
|
|
||||||
int dx=0;
|
int dx=0;
|
||||||
Theme::WindowStyle *winstyle = m_win->getScreen()->getWindowStyle();
|
Theme::WindowStyle *winstyle = m_win->getScreen()->getWindowStyle();
|
||||||
size_t dlen = m_win->getTitle().size();
|
size_t dlen = m_win->getTitle().size();
|
||||||
size_t l = winstyle->tab.font.textWidth(m_win->getTitle().c_str(), dlen);
|
size_t l = winstyle->tab.font.textWidth(m_win->getTitle().c_str(), dlen);
|
||||||
|
|
||||||
|
size_t max_width = m_size_w; // special cases in rotated mode
|
||||||
|
if (winstyle->tab.font.isRotated())
|
||||||
|
max_width = m_size_h;
|
||||||
|
|
||||||
if ( l > m_size_w) {
|
if ( l > m_size_w) {
|
||||||
for (; dlen >= 0; dlen--) {
|
for (; dlen >= 0; dlen--) {
|
||||||
l = winstyle->tab.font.textWidth(m_win->getTitle().c_str(), dlen) + m_win->frame.bevel_w*4;
|
l = winstyle->tab.font.textWidth(m_win->getTitle().c_str(), dlen) + m_win->frame.bevel_w*4;
|
||||||
|
|
||||||
if (l < m_size_w || dlen == 0)
|
if (l < max_width || dlen == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (winstyle->tab.justify) {
|
switch (winstyle->tab.justify) {
|
||||||
case DrawUtil::Font::RIGHT:
|
case DrawUtil::Font::RIGHT:
|
||||||
dx += m_size_w - l - m_win->frame.bevel_w*3;
|
dx += max_width - l - m_win->frame.bevel_w*3;
|
||||||
break;
|
break;
|
||||||
case DrawUtil::Font::CENTER:
|
case DrawUtil::Font::CENTER:
|
||||||
dx += (m_size_w - l) / 2;
|
dx += (max_width - l) / 2;
|
||||||
break;
|
break;
|
||||||
case DrawUtil::Font::LEFT:
|
case DrawUtil::Font::LEFT:
|
||||||
dx = m_win->frame.bevel_w;
|
dx = m_win->frame.bevel_w;
|
||||||
|
@ -412,13 +399,20 @@ void Tab::draw(bool pressed) const {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_win->getScreen()->getWindowStyle()->tab.font.drawText(
|
int dy = winstyle->tab.font.ascent() + m_win->frame.bevel_w;
|
||||||
|
// swap dx and dy if we're rotated
|
||||||
|
if (winstyle->tab.font.isRotated()) {
|
||||||
|
int tmp = dy;
|
||||||
|
dy = m_size_h - dx; // upside down
|
||||||
|
dx = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
winstyle->tab.font.drawText(
|
||||||
m_tabwin,
|
m_tabwin,
|
||||||
m_win->getScreen()->getScreenNumber(),
|
m_win->getScreen()->getScreenNumber(),
|
||||||
gc,
|
gc,
|
||||||
m_win->getTitle().c_str(), dlen,
|
m_win->getTitle().c_str(), dlen,
|
||||||
dx,
|
dx, dy);
|
||||||
m_win->getScreen()->getWindowStyle()->tab.font.ascent() + m_win->frame.bevel_w);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/Theme.cc
13
src/Theme.cc
|
@ -21,7 +21,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: Theme.cc,v 1.34 2002/11/15 13:10:48 fluxgen Exp $
|
// $Id: Theme.cc,v 1.35 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
@ -471,17 +471,6 @@ void Theme::loadTabStyle() {
|
||||||
|
|
||||||
loadFontFromDatabase(m_windowstyle.tab.font, "window.tab.font", "Window.Tab.Font");
|
loadFontFromDatabase(m_windowstyle.tab.font, "window.tab.font", "Window.Tab.Font");
|
||||||
|
|
||||||
//TODO: fix rotated font
|
|
||||||
//--------- rotated font for left and right tabs
|
|
||||||
// TODO: add extra checking
|
|
||||||
/*if (XrmGetResource(m_database, "window.tab.font", "Window.Tab.Font",
|
|
||||||
&value_type, &value)) {
|
|
||||||
if (! (m_windowstyle.tab.rot_font = DrawUtil::XRotLoadFont(m_display, value.addr, 90.0)) )
|
|
||||||
m_windowstyle.tab.rot_font = DrawUtil::XRotLoadFont(m_display, "fixed", 90);
|
|
||||||
} else
|
|
||||||
m_windowstyle.tab.rot_font = DrawUtil::XRotLoadFont(m_display, "fixed", 90);
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (XrmGetResource(m_database, "window.tab.justify", "Window.Tab.Justify",
|
if (XrmGetResource(m_database, "window.tab.justify", "Window.Tab.Justify",
|
||||||
&value_type, &value)) {
|
&value_type, &value)) {
|
||||||
if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
|
if (strstr(value.addr, "right") || strstr(value.addr, "Right"))
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: Theme.hh,v 1.17 2002/10/29 16:06:23 fluxgen Exp $
|
// $Id: Theme.hh,v 1.18 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#ifndef THEME_HH
|
#ifndef THEME_HH
|
||||||
#define THEME_HH
|
#define THEME_HH
|
||||||
|
@ -82,7 +82,6 @@ public:
|
||||||
FbTk::Color border_color;
|
FbTk::Color border_color;
|
||||||
unsigned int border_width;
|
unsigned int border_width;
|
||||||
unsigned int border_width_2x;
|
unsigned int border_width_2x;
|
||||||
DrawUtil::XRotFontStruct *rot_font;
|
|
||||||
} tab;
|
} tab;
|
||||||
|
|
||||||
} WindowStyle;
|
} WindowStyle;
|
||||||
|
|
314
src/XFontImp.cc
314
src/XFontImp.cc
|
@ -19,15 +19,18 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: XFontImp.cc,v 1.1 2002/10/13 22:22:14 fluxgen Exp $
|
// $Id: XFontImp.cc,v 1.2 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#include "XFontImp.hh"
|
#include "XFontImp.hh"
|
||||||
#include "BaseDisplay.hh"
|
#include "BaseDisplay.hh"
|
||||||
|
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
XFontImp::XFontImp(const char *fontname):m_fontstruct(0) {
|
XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0),
|
||||||
|
m_angle(0) {
|
||||||
if (fontname != 0)
|
if (fontname != 0)
|
||||||
load(fontname);
|
load(fontname);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +38,17 @@ XFontImp::XFontImp(const char *fontname):m_fontstruct(0) {
|
||||||
XFontImp::~XFontImp() {
|
XFontImp::~XFontImp() {
|
||||||
if (m_fontstruct != 0)
|
if (m_fontstruct != 0)
|
||||||
XFreeFont(BaseDisplay::getXDisplay(), m_fontstruct);
|
XFreeFont(BaseDisplay::getXDisplay(), m_fontstruct);
|
||||||
|
if (m_rotfont != 0)
|
||||||
|
freeRotFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
int XFontImp::ascent() const {
|
||||||
|
if (m_fontstruct == 0)
|
||||||
|
return 0;
|
||||||
|
if (m_rotfont != 0)
|
||||||
|
return m_rotfont->max_ascent;
|
||||||
|
|
||||||
|
return m_fontstruct->ascent;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XFontImp::load(const std::string &fontname) {
|
bool XFontImp::load(const std::string &fontname) {
|
||||||
|
@ -51,14 +65,26 @@ bool XFontImp::load(const std::string &fontname) {
|
||||||
void XFontImp::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
|
void XFontImp::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
|
||||||
if (m_fontstruct == 0)
|
if (m_fontstruct == 0)
|
||||||
return;
|
return;
|
||||||
|
// use roated font functions?
|
||||||
|
if (m_rotfont != 0) {
|
||||||
|
drawRotText(w, screen, gc, text, len, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Display *disp = BaseDisplay::getXDisplay();
|
Display *disp = BaseDisplay::getXDisplay();
|
||||||
XSetFont(disp, gc, m_fontstruct->fid);
|
XSetFont(disp, gc, m_fontstruct->fid);
|
||||||
XDrawString(disp, w, gc, x, y, text, len);
|
XDrawString(disp, w, gc, x, y, text, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const {
|
unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const {
|
||||||
|
if (text == 0)
|
||||||
|
return 0;
|
||||||
if (m_fontstruct == 0)
|
if (m_fontstruct == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
// check rotated font?
|
||||||
|
if (m_rotfont != 0)
|
||||||
|
return rotTextWidth(text, size);
|
||||||
|
|
||||||
return XTextWidth(m_fontstruct, text, size);
|
return XTextWidth(m_fontstruct, text, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,3 +94,287 @@ unsigned int XFontImp::height() const {
|
||||||
|
|
||||||
return m_fontstruct->ascent + m_fontstruct->descent;
|
return m_fontstruct->ascent + m_fontstruct->descent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XFontImp::rotate(float angle) {
|
||||||
|
//we must have a font loaded before we rotate
|
||||||
|
if (m_fontstruct == 0)
|
||||||
|
return;
|
||||||
|
if (m_rotfont != 0)
|
||||||
|
freeRotFont();
|
||||||
|
// no need for rotating, use regular font
|
||||||
|
if (angle == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//get positive angle
|
||||||
|
while (angle < 0)
|
||||||
|
angle += 360;
|
||||||
|
|
||||||
|
char val;
|
||||||
|
XImage *I1, *I2;
|
||||||
|
// X system default vars
|
||||||
|
Display *dpy = BaseDisplay::instance()->getXDisplay();
|
||||||
|
Window rootwin = DefaultRootWindow(dpy);
|
||||||
|
int screen = DefaultScreen(dpy);
|
||||||
|
|
||||||
|
GC font_gc;
|
||||||
|
char text[3];
|
||||||
|
int ichar, i, j, index, boxlen = 60;
|
||||||
|
int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
|
||||||
|
int min_char, max_char;
|
||||||
|
unsigned char *vertdata, *bitdata;
|
||||||
|
int ascent, descent, lbearing, rbearing;
|
||||||
|
|
||||||
|
// get nearest vertical or horizontal direction
|
||||||
|
int dir = (int)((angle+45.0)/90.0)%4;
|
||||||
|
|
||||||
|
if (dir == 0) // no rotation
|
||||||
|
return;
|
||||||
|
|
||||||
|
// create the depth 1 canvas bitmap
|
||||||
|
Pixmap canvas = XCreatePixmap(dpy, rootwin, boxlen, boxlen, 1);
|
||||||
|
|
||||||
|
// create graphic context for our canvas
|
||||||
|
font_gc = XCreateGC(dpy, canvas, 0, 0);
|
||||||
|
|
||||||
|
XSetBackground(dpy, font_gc, None);
|
||||||
|
|
||||||
|
XSetFont(dpy, font_gc, m_fontstruct->fid);
|
||||||
|
|
||||||
|
// allocate space for rotated font
|
||||||
|
m_rotfont = new(nothrow) XRotFontStruct;
|
||||||
|
|
||||||
|
if (m_rotfont == 0) {
|
||||||
|
cerr<<"RotFont: out of memory"<<endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine which characters are defined in font
|
||||||
|
min_char = m_fontstruct->min_char_or_byte2;
|
||||||
|
max_char = m_fontstruct->max_char_or_byte2;
|
||||||
|
|
||||||
|
// we only want printable chars
|
||||||
|
if (min_char<32)
|
||||||
|
min_char = 32;
|
||||||
|
if (max_char>126)
|
||||||
|
max_char = 126;
|
||||||
|
|
||||||
|
/* some overall font data ... */
|
||||||
|
m_rotfont->dir = dir;
|
||||||
|
m_rotfont->min_char = min_char;
|
||||||
|
m_rotfont->max_char = max_char;
|
||||||
|
m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent;
|
||||||
|
m_rotfont->max_descent = m_fontstruct->max_bounds.descent;
|
||||||
|
m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent;
|
||||||
|
|
||||||
|
// font needs rotation
|
||||||
|
// loop through each character
|
||||||
|
for (ichar = min_char; ichar <= max_char; ichar++) {
|
||||||
|
index = ichar - m_fontstruct->min_char_or_byte2;
|
||||||
|
|
||||||
|
// per char dimensions ...
|
||||||
|
ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent;
|
||||||
|
descent = m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent;
|
||||||
|
lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing;
|
||||||
|
rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing;
|
||||||
|
m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width;
|
||||||
|
|
||||||
|
// some space chars have zero body, but a bitmap can't have
|
||||||
|
if (!ascent && !descent)
|
||||||
|
ascent = m_rotfont->per_char[ichar-32].ascent = 1;
|
||||||
|
if (!lbearing && !rbearing)
|
||||||
|
rbearing = m_rotfont->per_char[ichar-32].rbearing = 1;
|
||||||
|
|
||||||
|
// glyph width and height when vertical
|
||||||
|
vert_w = rbearing - lbearing;
|
||||||
|
vert_h = ascent + descent;
|
||||||
|
|
||||||
|
// width in bytes
|
||||||
|
vert_len = (vert_w-1)/8+1;
|
||||||
|
|
||||||
|
XSetForeground(dpy, font_gc, None);
|
||||||
|
XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
|
||||||
|
|
||||||
|
// draw the character centre top right on canvas
|
||||||
|
sprintf(text, "%c", ichar);
|
||||||
|
XSetForeground(dpy, font_gc, 1);
|
||||||
|
XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
|
||||||
|
boxlen/2 - descent, text, 1);
|
||||||
|
|
||||||
|
// reserve memory for first XImage
|
||||||
|
vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
|
||||||
|
|
||||||
|
/* create the XImage ... */
|
||||||
|
I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
|
||||||
|
0, (char *)vertdata, vert_w, vert_h, 8, 0);
|
||||||
|
|
||||||
|
if (I1 == None) {
|
||||||
|
cerr<<"RotFont: Cant create ximage."<<endl;
|
||||||
|
delete m_rotfont;
|
||||||
|
m_rotfont = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
I1->byte_order = I1->bitmap_bit_order = MSBFirst;
|
||||||
|
|
||||||
|
/* extract character from canvas ... */
|
||||||
|
XGetSubImage(dpy, canvas, boxlen/2, boxlen/2 - vert_h,
|
||||||
|
vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
|
||||||
|
I1->format = XYBitmap;
|
||||||
|
|
||||||
|
/* width, height of rotated character ... */
|
||||||
|
if (dir == 2) {
|
||||||
|
bit_w = vert_w;
|
||||||
|
bit_h = vert_h;
|
||||||
|
} else {
|
||||||
|
bit_w = vert_h;
|
||||||
|
bit_h = vert_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* width in bytes ... */
|
||||||
|
bit_len = (bit_w-1)/8 + 1;
|
||||||
|
|
||||||
|
m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
|
||||||
|
m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
|
||||||
|
|
||||||
|
/* reserve memory for the rotated image ... */
|
||||||
|
bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1);
|
||||||
|
|
||||||
|
/* create the image ... */
|
||||||
|
I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
|
||||||
|
(char *)bitdata, bit_w, bit_h, 8, 0);
|
||||||
|
|
||||||
|
if (I2 == None) {
|
||||||
|
cerr<<"XFontImp: Cant create ximage!"<<endl;
|
||||||
|
delete m_rotfont;
|
||||||
|
m_rotfont = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
I2->byte_order = I2->bitmap_bit_order = MSBFirst;
|
||||||
|
|
||||||
|
/* map vertical data to rotated character ... */
|
||||||
|
for (j = 0; j < bit_h; j++) {
|
||||||
|
for (i = 0; i < bit_w; i++) {
|
||||||
|
/* map bits ... */
|
||||||
|
if (dir == 1) {
|
||||||
|
val = vertdata[i*vert_len + (vert_w-j-1)/8] &
|
||||||
|
(128>>((vert_w-j-1)%8));
|
||||||
|
} else if (dir == 2) {
|
||||||
|
val = vertdata[(vert_h-j-1)*vert_len +
|
||||||
|
(vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
|
||||||
|
} else {
|
||||||
|
val = vertdata[(vert_h-i-1)*vert_len + j/8] &
|
||||||
|
(128>>(j%8));
|
||||||
|
}
|
||||||
|
if (val) {
|
||||||
|
bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
|
||||||
|
(128>>(i%8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create this character's bitmap
|
||||||
|
m_rotfont->per_char[ichar-32].glyph.bm =
|
||||||
|
XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1);
|
||||||
|
|
||||||
|
// put the image into the bitmap
|
||||||
|
XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm,
|
||||||
|
font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
|
||||||
|
|
||||||
|
// free the image and data
|
||||||
|
XDestroyImage(I1);
|
||||||
|
XDestroyImage(I2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free pixmap and GC ... */
|
||||||
|
XFreePixmap(dpy, canvas);
|
||||||
|
XFreeGC(dpy, font_gc);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void XFontImp::freeRotFont() {
|
||||||
|
if (m_rotfont == 0)
|
||||||
|
return;
|
||||||
|
// loop through each character and free its pixmap
|
||||||
|
for (int ichar = m_rotfont->min_char - 32;
|
||||||
|
ichar <= m_rotfont->max_char - 32; ++ichar) {
|
||||||
|
XFreePixmap(BaseDisplay::instance()->getXDisplay(), m_rotfont->per_char[ichar].glyph.bm);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete m_rotfont;
|
||||||
|
m_rotfont = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
|
||||||
|
|
||||||
|
Display *dpy = BaseDisplay::instance()->getXDisplay();
|
||||||
|
static GC my_gc = 0;
|
||||||
|
int xp, yp, dir, ichar;
|
||||||
|
|
||||||
|
if (text == NULL || len<1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dir = m_rotfont->dir;
|
||||||
|
if (my_gc == 0)
|
||||||
|
my_gc = XCreateGC(dpy, w, 0, 0);
|
||||||
|
|
||||||
|
XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
|
||||||
|
|
||||||
|
// vertical or upside down
|
||||||
|
|
||||||
|
XSetFillStyle(dpy, my_gc, FillStippled);
|
||||||
|
|
||||||
|
// loop through each character in texting
|
||||||
|
for (size_t i = 0; i<len; i++) {
|
||||||
|
ichar = text[i]-32;
|
||||||
|
|
||||||
|
// make sure it's a printing character
|
||||||
|
if (ichar >= 0 && ichar<95) {
|
||||||
|
// suitable offset
|
||||||
|
if (dir == 1) {
|
||||||
|
xp = x-m_rotfont->per_char[ichar].ascent;
|
||||||
|
yp = y-m_rotfont->per_char[ichar].rbearing;
|
||||||
|
} else if (dir == 2) {
|
||||||
|
xp = x-m_rotfont->per_char[ichar].rbearing;
|
||||||
|
yp = y-m_rotfont->per_char[ichar].descent+1;
|
||||||
|
} else {
|
||||||
|
xp = x-m_rotfont->per_char[ichar].descent+1;
|
||||||
|
yp = y+m_rotfont->per_char[ichar].lbearing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the glyph
|
||||||
|
XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm);
|
||||||
|
|
||||||
|
XSetTSOrigin(dpy, my_gc, xp, yp);
|
||||||
|
|
||||||
|
XFillRectangle(dpy, w, my_gc, xp, yp,
|
||||||
|
m_rotfont->per_char[ichar].glyph.bit_w,
|
||||||
|
m_rotfont->per_char[ichar].glyph.bit_h);
|
||||||
|
|
||||||
|
// advance position
|
||||||
|
if (dir == 1)
|
||||||
|
y -= m_rotfont->per_char[ichar].width;
|
||||||
|
else if (dir == 2)
|
||||||
|
x -= m_rotfont->per_char[ichar].width;
|
||||||
|
else
|
||||||
|
y += m_rotfont->per_char[ichar].width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const {
|
||||||
|
|
||||||
|
if (text == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned int width = 0;
|
||||||
|
for (size_t i = 0; i<size; i++) {
|
||||||
|
int ichar = text[i] - 32;
|
||||||
|
// make sure it's a printing character
|
||||||
|
if (ichar >= 0 && ichar < 95)
|
||||||
|
width += m_rotfont->per_char[ichar].width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// $Id: XFontImp.hh,v 1.3 2002/10/19 13:58:47 fluxgen Exp $
|
// $Id: XFontImp.hh,v 1.4 2002/11/25 14:07:21 fluxgen Exp $
|
||||||
|
|
||||||
#ifndef XFONTIMP_HH
|
#ifndef XFONTIMP_HH
|
||||||
#define XFONTIMP_HH
|
#define XFONTIMP_HH
|
||||||
|
@ -33,12 +33,46 @@ public:
|
||||||
bool load(const std::string &filename);
|
bool load(const std::string &filename);
|
||||||
unsigned int textWidth(const char * const text, unsigned int size) const;
|
unsigned int textWidth(const char * const text, unsigned int size) const;
|
||||||
unsigned int height() const;
|
unsigned int height() const;
|
||||||
int ascent() const { return m_fontstruct ? m_fontstruct->ascent : 0; }
|
float angle() const { return m_angle; }
|
||||||
|
int ascent() const;
|
||||||
int descent() const { return m_fontstruct ? m_fontstruct->descent : 0; }
|
int descent() const { return m_fontstruct ? m_fontstruct->descent : 0; }
|
||||||
void drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const;
|
void drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const;
|
||||||
bool loaded() const { return m_fontstruct != 0; }
|
bool loaded() const { return m_fontstruct != 0; }
|
||||||
|
void rotate(float angle);
|
||||||
private:
|
private:
|
||||||
|
void freeRotFont();
|
||||||
|
void drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const;
|
||||||
|
unsigned int rotTextWidth(const char * const text, unsigned int size) const;
|
||||||
|
struct BitmapStruct {
|
||||||
|
int bit_w;
|
||||||
|
int bit_h;
|
||||||
|
|
||||||
|
Pixmap bm;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XRotCharStruct {
|
||||||
|
int ascent;
|
||||||
|
int descent;
|
||||||
|
int lbearing;
|
||||||
|
int rbearing;
|
||||||
|
int width;
|
||||||
|
|
||||||
|
BitmapStruct glyph;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XRotFontStruct {
|
||||||
|
int dir;
|
||||||
|
int height;
|
||||||
|
int max_ascent;
|
||||||
|
int max_descent;
|
||||||
|
int max_char;
|
||||||
|
int min_char;
|
||||||
|
|
||||||
|
XRotCharStruct per_char[95];
|
||||||
|
};
|
||||||
|
XRotFontStruct *m_rotfont;
|
||||||
XFontStruct *m_fontstruct;
|
XFontStruct *m_fontstruct;
|
||||||
|
float m_angle;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // XFONTIMP_HH
|
#endif // XFONTIMP_HH
|
||||||
|
|
Loading…
Reference in a new issue