// See http://mathworld.wolfram.com/LeastSquaresFitting.html for illustration; // we calculate vertical (or horizontal) offsets from the line rather than // perpendicular offsets double Utility::getPointDeviation(const VisualLine &aLine, const int x, const int y) { // Bigger change in x than in y, nearer to horizontal than vertical if ( abs(aLine.end.x - aLine.start.x) > abs(aLine.end.y - aLine.start.y) ) { double lineY = getLineY(x, aLine); return fabs(y - lineY); } // Perfectly vertical; no need to find where the point would hit. // Hack. else if (aLine.left == aLine.right) { return abs(aLine.left - x); } // A line that is not perfectly vertical but is more vertical than horizontal else { double lineX = getLineX(y, aLine); return fabs(x - lineX); } }
/** * Draws all the characters in the text with a really * nasty complex gritty text rendering algorithm logic stuff. */ void Text::draw() { Surface::draw(); if (_text.empty() || _font == 0) { return; } // Show text borders for debugging if (Options::debugUi) { SDL_Rect r; r.w = getWidth(); r.h = getHeight(); r.x = 0; r.y = 0; this->drawRect(&r, 5); r.w-=2; r.h-=2; r.x++; r.y++; this->drawRect(&r, 0); } int x = 0, y = 0, line = 0, height = 0; Font *font = _font; int color = _color; std::wstring *s = &_text; for (std::vector<int>::iterator i = _lineHeight.begin(); i != _lineHeight.end(); ++i) { height += *i; } switch (_valign) { case ALIGN_TOP: y = 0; break; case ALIGN_MIDDLE: y = (int)ceil((getHeight() - height) / 2.0); break; case ALIGN_BOTTOM: y = getHeight() - height; break; } x = getLineX(line); if (_wrap) { s = &_wrappedText; } // Set up text color int mul = 1; if (_contrast) { mul = 3; } // Set up text direction int dir = 1; if (_lang->getTextDirection() == DIRECTION_RTL) { dir = -1; } // Invert text by inverting the font palette on index 3 (font palettes use indices 1-5) int mid = _invert ? 3 : 0; // Draw each letter one by one for (std::wstring::iterator c = s->begin(); c != s->end(); ++c) { if (Font::isSpace(*c)) { x += dir * font->getCharSize(*c).w; } else if (Font::isLinebreak(*c)) { line++; y += font->getCharSize(*c).h; x = getLineX(line); if (*c == L'\x02') { font = _small; } } else if (*c == L'\x01') { color = (color == _color ? _color2 : _color); } else { if (dir < 0) x += dir * font->getCharSize(*c).w; Surface* chr = font->getChar(*c); chr->setX(x); chr->setY(y); ShaderDraw<PaletteShift>(ShaderSurface(this, 0, 0), ShaderCrop(chr), ShaderScalar(color), ShaderScalar(mul), ShaderScalar(mid)); if (dir > 0) x += dir * font->getCharSize(*c).w; } } }
int Utility::getLineX(int y, const VisualLine &aLine) { return getLineX(y, aLine.b, aLine.a); }