/* AbiSource Application Framework * Copyright (C) 1998 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 <stdio.h> #include <string.h> #include <stdlib.h> #include "ut_debugmsg.h" #include "ut_assert.h" #include "ut_types.h" #include "ut_string.h" #include "gr_Graphics.h" #include "gr_Painter.h" #include "xap_Draw_Symbol.h" XAP_Draw_Symbol::XAP_Draw_Symbol(GR_Graphics * gc) : XAP_Preview(gc), m_areagc(NULL), m_pFont(NULL), m_drawWidth(0), m_drawHeight(0), m_drawareaWidth(0), m_drawareaHeight(0), m_CurrentSymbol(UCS_SPACE), m_PreviousSymbol(UCS_SPACE), m_vCharSet(256), m_stFont("Symbol") { } XAP_Draw_Symbol::~XAP_Draw_Symbol(void) { } void XAP_Draw_Symbol::setWindowSize( UT_uint32 width, UT_uint32 height) { m_drawWidth = m_gc->tlu(width); m_drawHeight = m_gc->tlu(height); } void XAP_Draw_Symbol::setAreaGc( GR_Graphics * gc) { m_areagc = gc; } void XAP_Draw_Symbol::setAreaSize( UT_uint32 width, UT_uint32 height) { m_drawareaWidth = m_areagc->tlu(width); m_drawareaHeight = m_areagc->tlu(height); setFontStringarea(); } void XAP_Draw_Symbol::setFontString( void ) { setFontToGC(m_gc, m_drawWidth / 32, 14); } void XAP_Draw_Symbol::setFontToGC(GR_Graphics *p_gc, UT_uint32 MaxWidthAllowable, UT_sint32 PointSize) { UT_ASSERT(p_gc); UT_ASSERT(MaxWidthAllowable); GR_Font* font = NULL; int SizeOK = false; UT_UCSChar p_buffer[224]; for(int i = 0; i < 224; i++) p_buffer[i] = i + 32; char temp[10]; while (!SizeOK) { sprintf(temp, "%ipt", PointSize); font = p_gc->findFont(m_stFont.c_str(), "normal", "", "normal", "", temp); /* findFont does a fuzzy match. If the font found doesn't have the same family name * that we asked for, we retrieve the new name and we use it */ if (font->getFamily()) m_stFont = font->getFamily(); p_gc->setFont(font); UT_uint32 MaxWidth = p_gc->getMaxCharacterWidth(p_buffer, 224); if (MaxWidth < MaxWidthAllowable) SizeOK = true; else { PointSize--; UT_ASSERT(PointSize); } } p_gc->getCoverage(m_vCharSet); } const char* XAP_Draw_Symbol::getSelectedFont() { return m_stFont.c_str(); } void XAP_Draw_Symbol::setSelectedFont(const char *font) { m_stFont = font; setFontString(); setFontStringarea(); m_CurrentSymbol = m_PreviousSymbol = UCS_SPACE; } void XAP_Draw_Symbol::setFontStringarea(void) { setFontToGC(m_areagc, m_drawareaWidth, 32); } void XAP_Draw_Symbol::draw(void) { UT_ASSERT(m_gc); UT_uint32 wwidth, wheight, yoff, xoff, x, y; size_t i; GR_Painter painter(m_gc); wwidth = m_drawWidth; wheight = m_drawHeight; UT_uint32 tmpw = wwidth / 32; UT_uint32 tmph = wheight / 7; yoff = wheight / 14; xoff = wwidth / 64; painter.clearArea(0, 0, wwidth, wheight); int pos = 0; for (i = 0; i < m_vCharSet.size(); i += 2) { UT_UCSChar base = static_cast<UT_UCSChar>(m_vCharSet[i]); size_t nb_chars = static_cast<size_t>(m_vCharSet[i + 1]); for (UT_UCSChar j = base; j < base + nb_chars; ++j) { unsigned short w = m_gc->measureUnRemappedChar(j); UT_uint32 x = (pos % 32) * tmpw + (tmpw - w) / 2; UT_uint32 y = pos / 32 * tmph; painter.drawChars(&j, 0, 1, x, y); ++pos; } } y = 0; for(i = 0; i <= 6; i++) { painter.drawLine(0, y, wwidth - m_areagc->tlu(1), y); y += tmph; } x = 0; for(i = 0; i <= 31; i++) { painter.drawLine(x, 0, x, wheight - m_areagc->tlu(1)); x += tmpw; } } UT_UCSChar XAP_Draw_Symbol::calcSymbolFromCoords(UT_uint32 ix, UT_uint32 iy) { UT_uint32 index,count; index = iy * 32 + ix; count = 0; UT_DEBUGMSG(("calcSymbolFromCoords(x = [%u], y = [%u]) =", ix, iy)); for (size_t i = 0; i < m_vCharSet.size(); i += 2) { count += m_vCharSet[i + 1]; if (count > index) { UT_DEBUGMSG((" %u\n", static_cast<UT_uint32>(m_vCharSet[i] + index - count + m_vCharSet[i + 1]))); return static_cast<UT_UCSChar>(m_vCharSet[i] + index - count + m_vCharSet[i + 1]); } } return static_cast<UT_UCSChar>(0); } UT_UCSChar XAP_Draw_Symbol::calcSymbol(UT_uint32 x, UT_uint32 y) { UT_uint32 width = m_drawWidth; UT_uint32 height = m_drawHeight; UT_uint32 ix; UT_uint32 iy; if (x > width || y > height) return static_cast<UT_UCSChar>(0); iy = m_gc->tlu(y) / (height / 7); ix = m_gc->tlu(x) / (width / 32); return calcSymbolFromCoords(ix, iy); } void XAP_Draw_Symbol::calculatePosition(UT_UCSChar c, UT_uint32 &x, UT_uint32 &y) { UT_uint32 index = 0; for (size_t i = 0; i < m_vCharSet.size(); i += 2) { UT_uint32 base = static_cast<UT_uint32>(m_vCharSet[i]); UT_uint32 size = static_cast<UT_uint32>(m_vCharSet[i + 1]); if (base + size > c) { index += c - base; break; } else index += size; } x = index % 32; y = index / 32; UT_DEBUGMSG(("[%d] -> (%d, %d)\n", c, x, y)); } void XAP_Draw_Symbol::setCurrent(UT_UCSChar c) { m_PreviousSymbol = m_CurrentSymbol; m_CurrentSymbol = c; drawarea(m_CurrentSymbol, m_PreviousSymbol); } void XAP_Draw_Symbol::drawarea(UT_UCSChar c, UT_UCSChar p) // // This function displays the symbol c into the Selected Area. // It also highlights the selected symbol in the Symbol Table. // { UT_ASSERT(m_areagc); UT_uint32 wwidth,wheight,x,y,cx,cy,px,py,swidth,sheight; UT_uint32 cx1,cy1,px1,py1; GR_Painter areaPainter(m_areagc); GR_Painter painter(m_gc); wwidth = m_drawareaWidth; wheight = m_drawareaHeight; // Center the character // Note: That's bogus. measureString will give us the horizontal advance of "c", // but we need the bounding box of "c" instead. To get it, we should use with FreeType face->bbox, // in windows we should use the (FIXME: find the right name, it was something as getCharABC(...) unsigned short w1 = m_areagc->measureUnRemappedChar(c); x = (m_drawareaWidth - w1) / 2; y = (m_drawareaHeight - m_areagc->getFontHeight()) / 2; areaPainter.clearArea(0, 0, wwidth, wheight); areaPainter.drawChars(&c, 0, 1, x, y); // // Calculate the cordinates of the current and previous symbol // along with the widths of the appropriate boxes. swidth = m_drawWidth; sheight = m_drawHeight; UT_uint32 tmpw = m_drawWidth / 32; UT_uint32 tmph = m_drawHeight / 7; calculatePosition(c, cx, cy); unsigned short wc = m_gc->measureUnRemappedChar(c); cx *= tmpw; cy *= tmph; cx1 = cx + tmpw; cy1 = cy + tmph; calculatePosition(p, px, py); unsigned short wp = m_gc->measureUnRemappedChar(p); px *= tmpw; py *= tmph; px1 = px + tmpw; py1 = py + tmph; // Redraw the Previous Character in black on White painter.clearArea(px + m_areagc->tlu(1), py + m_areagc->tlu(1), tmpw - m_areagc->tlu(1), tmph - m_areagc->tlu(1)); painter.drawChars(&p, 0, 1, px + (tmpw - wp) / 2, py); // Redraw the Current Character in black on Blue UT_RGBColor colour(128, 128, 192); painter.fillRect(colour, cx + m_areagc->tlu(1), cy + m_areagc->tlu(1), tmpw - m_areagc->tlu(1), tmph - m_areagc->tlu(1)); painter.drawChars(&c, 0, 1, cx + (tmpw - wc) / 2, cy); } void XAP_Draw_Symbol::onLeftButtonDown(UT_sint32 x, UT_sint32 y) { setCurrent(calcSymbol(x, y)); }