diff options
Diffstat (limited to 'src/ftgl/FTLayout')
-rw-r--r-- | src/ftgl/FTLayout/FTLayout.cpp | 80 | ||||
-rw-r--r-- | src/ftgl/FTLayout/FTLayoutGlue.cpp | 171 | ||||
-rw-r--r-- | src/ftgl/FTLayout/FTLayoutImpl.h | 56 | ||||
-rw-r--r-- | src/ftgl/FTLayout/FTSimpleLayout.cpp | 460 | ||||
-rw-r--r-- | src/ftgl/FTLayout/FTSimpleLayoutImpl.h | 225 |
5 files changed, 992 insertions, 0 deletions
diff --git a/src/ftgl/FTLayout/FTLayout.cpp b/src/ftgl/FTLayout/FTLayout.cpp new file mode 100644 index 0000000..d4298bd --- /dev/null +++ b/src/ftgl/FTLayout/FTLayout.cpp @@ -0,0 +1,80 @@ +/* + * FTGL - OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz> + * Copyright (c) 2008 Sam Hocevar <sam@zoy.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "FTGL/ftgl.h" + +#include "../FTFont/FTFontImpl.h" +#include "./FTLayoutImpl.h" + + +// +// FTLayout +// + + +FTLayout::FTLayout() +{ + impl = new FTLayoutImpl(); +} + + +FTLayout::FTLayout(FTLayoutImpl *pImpl) +{ + impl = pImpl; +} + + +FTLayout::~FTLayout() +{ + delete impl; +} + + +FT_Error FTLayout::Error() const +{ + return impl->err; +} + + +// +// FTLayoutImpl +// + + +FTLayoutImpl::FTLayoutImpl() : + err(0) +{ + ; +} + + +FTLayoutImpl::~FTLayoutImpl() +{ + ; +} + diff --git a/src/ftgl/FTLayout/FTLayoutGlue.cpp b/src/ftgl/FTLayout/FTLayoutGlue.cpp new file mode 100644 index 0000000..60f428d --- /dev/null +++ b/src/ftgl/FTLayout/FTLayoutGlue.cpp @@ -0,0 +1,171 @@ +/* + * FTGL - OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz> + * Copyright (c) 2008 Éric Beets <ericbeets@free.fr> + * Copyright (c) 2008 Sam Hocevar <sam@zoy.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "FTInternals.h" + +static const FTBBox static_ftbbox; + +FTGL_BEGIN_C_DECLS + +#define C_TOR(cname, cargs, cxxname, cxxarg, cxxtype) \ + FTGLlayout* cname cargs \ + { \ + cxxname *l = new cxxname cxxarg; \ + if(l->Error()) \ + { \ + delete l; \ + return NULL; \ + } \ + FTGLlayout *ftgl = (FTGLlayout *)malloc(sizeof(FTGLlayout)); \ + ftgl->ptr = l; \ + ftgl->type = cxxtype; \ + return ftgl; \ + } + +// FTSimpleLayout::FTSimpleLayout(); +C_TOR(ftglCreateSimpleLayout, (), FTSimpleLayout, (), LAYOUT_SIMPLE); + +#define C_FUN(cret, cname, cargs, cxxerr, cxxname, cxxarg) \ + cret cname cargs \ + { \ + if(!l || !l->ptr) \ + { \ + fprintf(stderr, "FTGL warning: NULL pointer in %s\n", #cname); \ + cxxerr; \ + } \ + return l->ptr->cxxname cxxarg; \ + } + +// FTLayout::~FTLayout(); +void ftglDestroyLayout(FTGLlayout *l) +{ + if(!l || !l->ptr) + { + fprintf(stderr, "FTGL warning: NULL pointer in %s\n", __FUNCTION__); + return; + } + delete l->ptr; + free(l); +} + +// virtual FTBBox FTLayout::BBox(const char* string) +extern "C++" { +C_FUN(static FTBBox, _ftgGetlLayoutBBox, (FTGLlayout *l, const char *s), + return static_ftbbox, BBox, (s)); +} + +void ftgGetlLayoutBBox(FTGLlayout *l, const char * s, float c[6]) +{ + FTBBox ret = _ftgGetlLayoutBBox(l, s); + FTPoint lower = ret.Lower(), upper = ret.Upper(); + c[0] = lower.Xf(); c[1] = lower.Yf(); c[2] = lower.Zf(); + c[3] = upper.Xf(); c[4] = upper.Yf(); c[5] = upper.Zf(); +} + +// virtual void FTLayout::Render(const char* string, int renderMode); +C_FUN(void, ftglRenderLayout, (FTGLlayout *l, const char *s, int r), + return, Render, (s, r)); + +// FT_Error FTLayout::Error() const; +C_FUN(FT_Error, ftglGetLayoutError, (FTGLlayout *l), return -1, Error, ()); + +// void FTSimpleLayout::SetFont(FTFont *fontInit) +void ftglSetLayoutFont(FTGLlayout *l, FTGLfont *font) +{ + if(!l || !l->ptr) + { + fprintf(stderr, "FTGL warning: NULL pointer in %s\n", __FUNCTION__); + return; + } + if(l->type != FTGL::LAYOUT_SIMPLE) + { + fprintf(stderr, "FTGL warning: %s not implemented for %d\n", + __FUNCTION__, l->type); + } + l->font = font; + return dynamic_cast<FTSimpleLayout*>(l->ptr)->SetFont(font->ptr); +} + +// FTFont *FTSimpleLayout::GetFont() +FTGLfont *ftglGetLayoutFont(FTGLlayout *l) +{ + if(!l || !l->ptr) + { + fprintf(stderr, "FTGL warning: NULL pointer in %s\n", __FUNCTION__); + return NULL; + } + if(l->type != FTGL::LAYOUT_SIMPLE) + { + fprintf(stderr, "FTGL warning: %s not implemented for %d\n", + __FUNCTION__, l->type); + } + return l->font; +} + +#undef C_FUN + +#define C_FUN(cret, cname, cargs, cxxerr, cxxname, cxxarg) \ + cret cname cargs \ + { \ + if(!l || !l->ptr) \ + { \ + fprintf(stderr, "FTGL warning: NULL pointer in %s\n", #cname); \ + cxxerr; \ + } \ + if(l->type != FTGL::LAYOUT_SIMPLE) \ + { \ + fprintf(stderr, "FTGL warning: %s not implemented for %d\n", \ + __FUNCTION__, l->type); \ + cxxerr; \ + } \ + return dynamic_cast<FTSimpleLayout*>(l->ptr)->cxxname cxxarg; \ + } + +// void FTSimpleLayout::SetLineLength(const float LineLength); +C_FUN(void, ftglSetLayoutLineLength, (FTGLlayout *l, const float length), + return, SetLineLength, (length)); + +// float FTSimpleLayout::GetLineLength() const +C_FUN(float, ftglGetLayoutLineLength, (FTGLlayout *l), + return 0.0f, GetLineLength, ()); + +// void FTSimpleLayout::SetAlignment(const TextAlignment Alignment) +C_FUN(void, ftglSetLayoutAlignment, (FTGLlayout *l, const int a), + return, SetAlignment, ((FTGL::TextAlignment)a)); + +// TextAlignment FTSimpleLayout::GetAlignment() const +C_FUN(int, ftglGetLayoutAlignement, (FTGLlayout *l), + return FTGL::ALIGN_LEFT, GetAlignment, ()); + +// void FTSimpleLayout::SetLineSpacing(const float LineSpacing) +C_FUN(void, ftglSetLayoutLineSpacing, (FTGLlayout *l, const float f), + return, SetLineSpacing, (f)); + +FTGL_END_C_DECLS + diff --git a/src/ftgl/FTLayout/FTLayoutImpl.h b/src/ftgl/FTLayout/FTLayoutImpl.h new file mode 100644 index 0000000..85df50d --- /dev/null +++ b/src/ftgl/FTLayout/FTLayoutImpl.h @@ -0,0 +1,56 @@ +/* + * FTGL - OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz> + * Copyright (c) 2008 Sam Hocevar <sam@zoy.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FTLayoutImpl__ +#define __FTLayoutImpl__ + +#include "FTSize.h" +#include "FTGlyphContainer.h" + + +class FTLayoutImpl +{ + friend class FTLayout; + + protected: + FTLayoutImpl(); + + virtual ~FTLayoutImpl(); + + protected: + /** + * Current pen or cursor position; + */ + FTPoint pen; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; +}; + +#endif // __FTLayoutImpl__ + diff --git a/src/ftgl/FTLayout/FTSimpleLayout.cpp b/src/ftgl/FTLayout/FTSimpleLayout.cpp new file mode 100644 index 0000000..b5a7beb --- /dev/null +++ b/src/ftgl/FTLayout/FTSimpleLayout.cpp @@ -0,0 +1,460 @@ +/* + * FTGL - OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz> + * Copyright (c) 2008 Sam Hocevar <sam@zoy.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include <ctype.h> +#include <wctype.h> + +#include "FTInternals.h" +#include "FTUnicode.h" + +#include "FTGlyphContainer.h" +#include "FTSimpleLayoutImpl.h" + + +// +// FTSimpleLayout +// + + +FTSimpleLayout::FTSimpleLayout() : + FTLayout(new FTSimpleLayoutImpl()) +{} + + +FTSimpleLayout::~FTSimpleLayout() +{} + + +FTBBox FTSimpleLayout::BBox(const char *string, const int len, FTPoint pos) +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->BBox(string, len, pos); +} + + +FTBBox FTSimpleLayout::BBox(const wchar_t *string, const int len, FTPoint pos) +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->BBox(string, len, pos); +} + + +void FTSimpleLayout::Render(const char *string, const int len, FTPoint pos, + int renderMode) +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->Render(string, len, pos, + renderMode); +} + + +void FTSimpleLayout::Render(const wchar_t* string, const int len, FTPoint pos, + int renderMode) +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->Render(string, len, pos, + renderMode); +} + + +void FTSimpleLayout::SetFont(FTFont *fontInit) +{ + dynamic_cast<FTSimpleLayoutImpl*>(impl)->currentFont = fontInit; +} + + +FTFont *FTSimpleLayout::GetFont() +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->currentFont; +} + + +void FTSimpleLayout::SetLineLength(const float LineLength) +{ + dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineLength = LineLength; +} + + +float FTSimpleLayout::GetLineLength() const +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineLength; +} + + +void FTSimpleLayout::SetAlignment(const FTGL::TextAlignment Alignment) +{ + dynamic_cast<FTSimpleLayoutImpl*>(impl)->alignment = Alignment; +} + + +FTGL::TextAlignment FTSimpleLayout::GetAlignment() const +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->alignment; +} + + +void FTSimpleLayout::SetLineSpacing(const float LineSpacing) +{ + dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineSpacing = LineSpacing; +} + + +float FTSimpleLayout::GetLineSpacing() const +{ + return dynamic_cast<FTSimpleLayoutImpl*>(impl)->lineSpacing; +} + + +// +// FTSimpleLayoutImpl +// + + +FTSimpleLayoutImpl::FTSimpleLayoutImpl() +{ + currentFont = NULL; + lineLength = 100.0f; + alignment = FTGL::ALIGN_LEFT; + lineSpacing = 1.0f; +} + + +template <typename T> +inline FTBBox FTSimpleLayoutImpl::BBoxI(const T* string, const int len, + FTPoint position) +{ + FTBBox tmp; + + WrapText(string, len, position, 0, &tmp); + + return tmp; +} + + +FTBBox FTSimpleLayoutImpl::BBox(const char *string, const int len, + FTPoint position) +{ + return BBoxI(string, len, position); +} + + +FTBBox FTSimpleLayoutImpl::BBox(const wchar_t *string, const int len, + FTPoint position) +{ + return BBoxI(string, len, position); +} + + +template <typename T> +inline void FTSimpleLayoutImpl::RenderI(const T *string, const int len, + FTPoint position, int renderMode) +{ + pen = FTPoint(0.0f, 0.0f); + WrapText(string, len, position, renderMode, NULL); +} + + +void FTSimpleLayoutImpl::Render(const char *string, const int len, + FTPoint position, int renderMode) +{ + RenderI(string, len, position, renderMode); +} + + +void FTSimpleLayoutImpl::Render(const wchar_t* string, const int len, + FTPoint position, int renderMode) +{ + RenderI(string, len, position, renderMode); +} + + +template <typename T> +inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len, + FTPoint position, int renderMode, + FTBBox *bounds) +{ + FTUnicodeStringItr<T> breakItr(buf); // points to the last break character + FTUnicodeStringItr<T> lineStart(buf); // points to the line start + float nextStart = 0.0; // total width of the current line + float breakWidth = 0.0; // width of the line up to the last word break + float currentWidth = 0.0; // width of all characters on the current line + float prevWidth; // width of all characters but the current glyph + float wordLength = 0.0; // length of the block since the last break char + int charCount = 0; // number of characters so far on the line + int breakCharCount = 0; // number of characters before the breakItr + float glyphWidth, advance; + FTBBox glyphBounds; + + // Reset the pen position + pen.Y(0); + + // If we have bounds mark them invalid + if(bounds) + { + bounds->Invalidate(); + } + + // Scan the input for all characters that need output + FTUnicodeStringItr<T> prevItr(buf); + for (FTUnicodeStringItr<T> itr(buf); *itr; prevItr = itr++, charCount++) + { + // Find the width of the current glyph + glyphBounds = currentFont->BBox(itr.getBufferFromHere(), 1); + glyphWidth = glyphBounds.Upper().Xf() - glyphBounds.Lower().Xf(); + + advance = currentFont->Advance(itr.getBufferFromHere(), 1); + prevWidth = currentWidth; + // Compute the width of all glyphs up to the end of buf[i] + currentWidth = nextStart + glyphWidth; + // Compute the position of the next glyph + nextStart += advance; + + // See if the current character is a space, a break or a regular character + if((currentWidth > lineLength) || (*itr == '\n')) + { + // A non whitespace character has exceeded the line length. Or a + // newline character has forced a line break. Output the last + // line and start a new line after the break character. + // If we have not yet found a break, break on the last character + if(breakItr == lineStart || (*itr == '\n')) + { + // Break on the previous character + breakItr = prevItr; + breakCharCount = charCount - 1; + breakWidth = prevWidth; + // None of the previous words will be carried to the next line + wordLength = 0; + // If the current character is a newline discard its advance + if(*itr == '\n') advance = 0; + } + + float remainingWidth = lineLength - breakWidth; + + // Render the current substring + FTUnicodeStringItr<T> breakChar = breakItr; + // move past the break character and don't count it on the next line either + ++breakChar; --charCount; + // If the break character is a newline do not render it + if(*breakChar == '\n') + { + ++breakChar; --charCount; + } + + OutputWrapped(lineStart.getBufferFromHere(), breakCharCount, + //breakItr.getBufferFromHere() - lineStart.getBufferFromHere(), + position, renderMode, remainingWidth, bounds); + + // Store the start of the next line + lineStart = breakChar; + // TODO: Is Height() the right value here? + pen -= FTPoint(0, currentFont->LineHeight() * lineSpacing); + // The current width is the width since the last break + nextStart = wordLength + advance; + wordLength += advance; + currentWidth = wordLength + advance; + // Reset the safe break for the next line + breakItr = lineStart; + charCount -= breakCharCount; + } + else if(iswspace(*itr)) + { + // This is the last word break position + wordLength = 0; + breakItr = itr; + breakCharCount = charCount; + + // Check to see if this is the first whitespace character in a run + if(buf == itr.getBufferFromHere() || !iswspace(*prevItr)) + { + // Record the width of the start of the block + breakWidth = currentWidth; + } + } + else + { + wordLength += advance; + } + } + + float remainingWidth = lineLength - currentWidth; + // Render any remaining text on the last line + // Disable justification for the last row + if(alignment == FTGL::ALIGN_JUSTIFY) + { + alignment = FTGL::ALIGN_LEFT; + OutputWrapped(lineStart.getBufferFromHere(), -1, position, renderMode, + remainingWidth, bounds); + alignment = FTGL::ALIGN_JUSTIFY; + } + else + { + OutputWrapped(lineStart.getBufferFromHere(), -1, position, renderMode, + remainingWidth, bounds); + } +} + + +void FTSimpleLayoutImpl::WrapText(const char *buf, const int len, + FTPoint position, int renderMode, + FTBBox *bounds) +{ + WrapTextI(buf, len, position, renderMode, bounds); +} + + +void FTSimpleLayoutImpl::WrapText(const wchar_t* buf, const int len, + FTPoint position, int renderMode, + FTBBox *bounds) +{ + WrapTextI(buf, len, position, renderMode, bounds); +} + + +template <typename T> +inline void FTSimpleLayoutImpl::OutputWrappedI(const T *buf, const int len, + FTPoint position, int renderMode, + const float remaining, + FTBBox *bounds) +{ + float distributeWidth = 0.0; + // Align the text according as specified by Alignment + switch (alignment) + { + case FTGL::ALIGN_LEFT: + pen.X(0); + break; + case FTGL::ALIGN_CENTER: + pen.X(remaining / 2); + break; + case FTGL::ALIGN_RIGHT: + pen.X(remaining); + break; + case FTGL::ALIGN_JUSTIFY: + pen.X(0); + distributeWidth = remaining; + break; + } + + // If we have bounds expand them by the line's bounds, otherwise render + // the line. + if(bounds) + { + FTBBox temp = currentFont->BBox(buf, len); + + // Add the extra space to the upper x dimension + temp = FTBBox(temp.Lower() + pen, + temp.Upper() + pen + FTPoint(distributeWidth, 0)); + + // See if this is the first area to be added to the bounds + if(bounds->IsValid()) + { + *bounds |= temp; + } + else + { + *bounds = temp; + } + } + else + { + RenderSpace(buf, len, position, renderMode, distributeWidth); + } +} + + +void FTSimpleLayoutImpl::OutputWrapped(const char *buf, const int len, + FTPoint position, int renderMode, + const float remaining, FTBBox *bounds) +{ + OutputWrappedI(buf, len, position, renderMode, remaining, bounds); +} + + +void FTSimpleLayoutImpl::OutputWrapped(const wchar_t *buf, const int len, + FTPoint position, int renderMode, + const float remaining, FTBBox *bounds) +{ + OutputWrappedI(buf, len, position, renderMode, remaining, bounds); +} + + +template <typename T> +inline void FTSimpleLayoutImpl::RenderSpaceI(const T *string, const int len, + FTPoint position, int renderMode, + const float extraSpace) +{ + float space = 0.0; + + // If there is space to distribute, count the number of spaces + if(extraSpace > 0.0) + { + int numSpaces = 0; + + // Count the number of space blocks in the input + FTUnicodeStringItr<T> prevItr(string), itr(string); + for(int i = 0; ((len < 0) && *itr) || ((len >= 0) && (i <= len)); + ++i, prevItr = itr++) + { + // If this is the end of a space block, increment the counter + if((i > 0) && !iswspace(*itr) && iswspace(*prevItr)) + { + numSpaces++; + } + } + + space = extraSpace/numSpaces; + } + + // Output all characters of the string + FTUnicodeStringItr<T> prevItr(string), itr(string); + for(int i = 0; ((len < 0) && *itr) || ((len >= 0) && (i <= len)); + ++i, prevItr = itr++) + { + // If this is the end of a space block, distribute the extra space + // inside it + if((i > 0) && !iswspace(*itr) && iswspace(*prevItr)) + { + pen += FTPoint(space, 0); + } + + pen = currentFont->Render(itr.getBufferFromHere(), 1, pen, FTPoint(), renderMode); + } +} + + +void FTSimpleLayoutImpl::RenderSpace(const char *string, const int len, + FTPoint position, int renderMode, + const float extraSpace) +{ + RenderSpaceI(string, len, position, renderMode, extraSpace); +} + + +void FTSimpleLayoutImpl::RenderSpace(const wchar_t *string, const int len, + FTPoint position, int renderMode, + const float extraSpace) +{ + RenderSpaceI(string, len, position, renderMode, extraSpace); +} + diff --git a/src/ftgl/FTLayout/FTSimpleLayoutImpl.h b/src/ftgl/FTLayout/FTSimpleLayoutImpl.h new file mode 100644 index 0000000..96a074d --- /dev/null +++ b/src/ftgl/FTLayout/FTSimpleLayoutImpl.h @@ -0,0 +1,225 @@ +/* + * FTGL - OpenGL font library + * + * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz> + * Copyright (c) 2008 Sam Hocevar <sam@zoy.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __FTSimpleLayoutImpl__ +#define __FTSimpleLayoutImpl__ + +#include "FTLayoutImpl.h" + + +class FTFont; + +class FTSimpleLayoutImpl : public FTLayoutImpl +{ + friend class FTSimpleLayout; + + protected: + FTSimpleLayoutImpl(); + + virtual ~FTSimpleLayoutImpl() {}; + + virtual FTBBox BBox(const char* string, const int len, + FTPoint position); + + virtual FTBBox BBox(const wchar_t* string, const int len, + FTPoint position); + + virtual void Render(const char *string, const int len, + FTPoint position, int renderMode); + + virtual void Render(const wchar_t *string, const int len, + FTPoint position, int renderMode); + + /** + * Render a string of characters and distribute extra space amongst + * the whitespace regions of the string. + * + * @param string A buffer of wchar_t characters to output. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param extraSpace The amount of extra space to distribute amongst + * the characters. + */ + virtual void RenderSpace(const char *string, const int len, + FTPoint position, int renderMode, + const float extraSpace); + + /** + * Render a string of characters and distribute extra space amongst + * the whitespace regions of the string. + * + * @param string A buffer of wchar_t characters to output. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param extraSpace The amount of extra space to distribute amongst + * the characters. + */ + virtual void RenderSpace(const wchar_t *string, const int len, + FTPoint position, int renderMode, + const float extraSpace); + + private: + /** + * Either render a string of characters and wrap lines + * longer than a threshold or compute the bounds + * of a string of characters when wrapped. The functionality + * of this method is exposed by the BBoxWrapped and + * RenderWrapped methods. + * + * @param buf A char string to output. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param bounds A pointer to a bounds object. If non null + * the bounds of the text when laid out + * will be stored in bounds. If null the + * text will be rendered. + */ + virtual void WrapText(const char *buf, const int len, + FTPoint position, int renderMode, + FTBBox *bounds); + + /** + * Either render a string of characters and wrap lines + * longer than a threshold or compute the bounds + * of a string of characters when wrapped. The functionality + * of this method is exposed by the BBoxWrapped and + * RenderWrapped methods. + * + * @param buf A wchar_t style string to output. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param bounds A pointer to a bounds object. If non null + * the bounds of the text when laid out + * will be stored in bounds. If null the + * text will be rendered. + */ + virtual void WrapText(const wchar_t *buf, const int len, + FTPoint position, int renderMode, + FTBBox *bounds); + + /** + * A helper method used by WrapText to either output the text or + * compute it's bounds. + * + * @param buf A pointer to an array of character data. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param RemainingWidth The amount of extra space left on the line. + * @param bounds A pointer to a bounds object. If non null the + * bounds will be initialized or expanded by the + * bounds of the line. If null the text will be + * rendered. If the bounds are invalid (lower > upper) + * they will be initialized. Otherwise they + * will be expanded. + */ + void OutputWrapped(const char *buf, const int len, + FTPoint position, int renderMode, + const float RemainingWidth, FTBBox *bounds); + + /** + * A helper method used by WrapText to either output the text or + * compute it's bounds. + * + * @param buf A pointer to an array of character data. + * @param len The length of the string. If < 0 then all characters + * will be displayed until a null character is encountered. + * @param position TODO + * @param renderMode Render mode to display + * @param RemainingWidth The amount of extra space left on the line. + * @param bounds A pointer to a bounds object. If non null the + * bounds will be initialized or expanded by the + * bounds of the line. If null the text will be + * rendered. If the bounds are invalid (lower > upper) + * they will be initialized. Otherwise they + * will be expanded. + */ + void OutputWrapped(const wchar_t *buf, const int len, + FTPoint position, int renderMode, + const float RemainingWidth, FTBBox *bounds); + + /** + * The font to use for rendering the text. The font is + * referenced by this but will not be disposed of when this + * is deleted. + */ + FTFont *currentFont; + + /** + * The maximum line length for formatting text. + */ + float lineLength; + + /** + * The text alignment mode used to distribute + * space within a line or rendered text. + */ + FTGL::TextAlignment alignment; + + /** + * The height of each line of text expressed as + * a percentage of the font's line height. + */ + float lineSpacing; + + /* Internal generic BBox() implementation */ + template <typename T> + inline FTBBox BBoxI(const T* string, const int len, FTPoint position); + + /* Internal generic Render() implementation */ + template <typename T> + inline void RenderI(const T* string, const int len, + FTPoint position, int renderMode); + + /* Internal generic RenderSpace() implementation */ + template <typename T> + inline void RenderSpaceI(const T* string, const int len, + FTPoint position, int renderMode, + const float extraSpace); + + /* Internal generic WrapText() implementation */ + template <typename T> + void WrapTextI(const T* buf, const int len, FTPoint position, + int renderMode, FTBBox *bounds); + + /* Internal generic OutputWrapped() implementation */ + template <typename T> + void OutputWrappedI(const T* buf, const int len, FTPoint position, + int renderMode, const float RemainingWidth, + FTBBox *bounds); +}; + +#endif // __FTSimpleLayoutImpl__ + |