1 /*
2  * FTGL - OpenGL font library
3  *
4  * Copyright (c) 2008 Sam Hocevar <sam@zoy.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include "../config.h"
27 
28 #include <string>
29 
30 #include "FTGL/ftgl.h"
31 
32 #include "../FTInternals.h"
33 #include "FTBufferGlyphImpl.h"
34 
35 
36 //
37 //  FTGLBufferGlyph
38 //
39 
40 
FTBufferGlyph(FT_GlyphSlot glyph,FTBuffer * buffer)41 FTBufferGlyph::FTBufferGlyph(FT_GlyphSlot glyph, FTBuffer *buffer) :
42     FTGlyph(new FTBufferGlyphImpl(glyph, buffer))
43 {}
44 
45 
~FTBufferGlyph()46 FTBufferGlyph::~FTBufferGlyph()
47 {}
48 
49 
Render(const FTPoint & pen,int renderMode)50 const FTPoint& FTBufferGlyph::Render(const FTPoint& pen, int renderMode)
51 {
52     FTBufferGlyphImpl *myimpl = dynamic_cast<FTBufferGlyphImpl *>(impl);
53     return myimpl->RenderImpl(pen, renderMode);
54 }
55 
56 
57 //
58 //  FTGLBufferGlyphImpl
59 //
60 
61 
FTBufferGlyphImpl(FT_GlyphSlot glyph,FTBuffer * p)62 FTBufferGlyphImpl::FTBufferGlyphImpl(FT_GlyphSlot glyph, FTBuffer *p)
63 :   FTGlyphImpl(glyph),
64     has_bitmap(false),
65     buffer(p)
66 {
67     err = FT_Render_Glyph(glyph, FT_RENDER_MODE_NORMAL);
68     if(err || glyph->format != ft_glyph_format_bitmap)
69     {
70         return;
71     }
72 
73     bitmap = glyph->bitmap;
74     pixels = new unsigned char[bitmap.pitch * bitmap.rows];
75     memcpy(pixels, bitmap.buffer, bitmap.pitch * bitmap.rows);
76 
77     if(bitmap.width && bitmap.rows)
78     {
79         has_bitmap = true;
80         corner = FTPoint(glyph->bitmap_left, glyph->bitmap_top);
81     }
82 }
83 
84 
~FTBufferGlyphImpl()85 FTBufferGlyphImpl::~FTBufferGlyphImpl()
86 {
87     delete[] pixels;
88 }
89 
90 
RenderImpl(const FTPoint & pen,int renderMode)91 const FTPoint& FTBufferGlyphImpl::RenderImpl(const FTPoint& pen, int renderMode)
92 {
93     if(has_bitmap)
94     {
95         FTPoint pos(buffer->Pos() + pen + corner);
96         int dx = (int)(pos.Xf() + 0.5f);
97         int dy = buffer->Height() - (int)(pos.Yf() + 0.5f);
98         unsigned char * dest = buffer->Pixels() + dx + dy * buffer->Width();
99 
100         for(int y = 0; y < bitmap.rows; y++)
101         {
102             // FIXME: change the loop bounds instead of doing this test
103             if(y + dy < 0 || y + dy >= buffer->Height()) continue;
104 
105             for(int x = 0; x < bitmap.width; x++)
106             {
107                 if(x + dx < 0 || x + dx >= buffer->Width()) continue;
108 
109                 unsigned char p = pixels[y * bitmap.pitch + x];
110 
111                 if(p)
112                 {
113                     dest[y * buffer->Width() + x] = p;
114                 }
115             }
116         }
117     }
118 
119     return advance;
120 }
121 
122