e0b3f630ebdb93d766c1731a0699575dbf44ded1
[WebKit-https.git] / Source / WebCore / platform / graphics / wince / FontWinCE.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2007-2009 Torch Mobile, Inc.
4  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5  * Copyright (C) 2008 Holger Hans Peter Freyther
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "config.h"
30 #include "Font.h"
31
32 #include "AffineTransform.h"
33 #include "FloatRect.h"
34 #include "FontCache.h"
35 #include "FontData.h"
36 #include "FontGlyphs.h"
37 #include "GlyphBuffer.h"
38 #include "GraphicsContext.h"
39 #include "IntRect.h"
40 #include "NotImplemented.h"
41 #include "TextRun.h"
42 #include "WidthIterator.h"
43 #include <wtf/MathExtras.h>
44 #include <wtf/OwnPtr.h>
45
46 #include <windows.h>
47
48 using namespace WTF::Unicode;
49
50 namespace WebCore {
51
52 HDC g_screenDC = GetDC(0);
53
54 class ScreenDcReleaser {
55 public:
56     ~ScreenDcReleaser()
57     {
58         ReleaseDC(0, g_screenDC);
59     }
60 };
61
62 ScreenDcReleaser releaseScreenDc;
63
64 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer,
65     unsigned from, unsigned numGlyphs, const FloatPoint& point) const
66 {
67     graphicsContext->drawText(fontData, glyphBuffer, from, numGlyphs, point);
68 }
69
70 class TextRunComponent {
71 public:
72     TextRunComponent() : m_textRun(0, 0) {}
73     TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int offset);
74     TextRunComponent(int spaces, const Font &font, int offset);
75     ~TextRunComponent() { m_textRun; }
76
77     bool isSpace() const { return m_spaces; }
78     int textLength() const { return m_spaces ? m_spaces : m_textRun.length(); }
79
80     TextRun m_textRun;
81     float m_width;
82     int m_offset;
83     int m_spaces;
84 };
85
86 TextRunComponent::TextRunComponent(const UChar *start, int length, const TextRun& parentTextRun, const Font &font, int o)
87     : m_textRun(start, length, 0, 0
88         , parentTextRun.allowsTrailingExpansion() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion
89         , parentTextRun.direction()
90         , parentTextRun.directionalOverride())
91     , m_offset(o)
92     , m_spaces(0)
93 {
94     m_textRun.setTabSize(parentTextRun.allowTabs(), parentTextRun.tabSize());
95
96     WidthIterator it(&font, m_textRun);
97     it.advance(m_textRun.length(), 0);
98     m_width = it.m_runWidthSoFar;
99 }
100
101 TextRunComponent::TextRunComponent(int s, const Font &font, int o)
102     : m_textRun(0, 0)
103     , m_offset(o)
104     , m_spaces(s)
105 {
106     m_width = s * font.primaryFont()->widthForGlyph(' ');
107 }
108
109 typedef Vector<TextRunComponent, 128> TextRunComponents;
110
111 static int generateComponents(TextRunComponents* components, const Font &font, const TextRun &run)
112 {
113     int letterSpacing = font.letterSpacing();
114     int wordSpacing = font.wordSpacing();
115     int padding = run.expansion();
116     int numSpaces = 0;
117     if (padding) {
118         for (int i = 0; i < run.length(); i++)
119             if (Font::treatAsSpace(run[i]))
120                 ++numSpaces;
121     }
122
123     int offset = 0;
124     if (letterSpacing) {
125         // need to draw every letter on it's own
126         int start = 0;
127         if (Font::treatAsSpace(run[0])) {
128             int add = 0;
129             if (numSpaces) {
130                 add = padding/numSpaces;
131                 padding -= add;
132                 --numSpaces;
133             }
134             components->append(TextRunComponent(1, font, offset));
135             offset += add + letterSpacing + components->last().m_width;
136             start = 1;
137         }
138         for (int i = 1; i < run.length(); ++i) {
139             UChar ch = run[i];
140             if (U16_IS_LEAD(ch) && U16_IS_TRAIL(run[i-1]))
141                 ch = U16_GET_SUPPLEMENTARY(ch, run[i-1]);
142             if (U16_IS_TRAIL(ch) || U_GET_GC_MASK(ch) & U_GC_MN_MASK)
143                 continue;
144             if (Font::treatAsSpace(run[i])) {
145                 int add = 0;
146                 if (i - start > 0) {
147                     components->append(TextRunComponent(run.characters16() + start, i - start,
148                                                         run, font, offset));
149                     offset += components->last().m_width + letterSpacing;
150                 }
151                 if (numSpaces) {
152                     add = padding/numSpaces;
153                     padding -= add;
154                     --numSpaces;
155                 }
156                 components->append(TextRunComponent(1, font, offset));
157                 offset += wordSpacing + add + components->last().m_width + letterSpacing;
158                 start = i + 1;
159                 continue;
160             }
161             if (i - start > 0) {
162                 components->append(TextRunComponent(run.characters16() + start, i - start,
163                                                     run,
164                                                     font, offset));
165                 offset += components->last().m_width + letterSpacing;
166             }
167             start = i;
168         }
169         if (run.length() - start > 0) {
170             components->append(TextRunComponent(run.characters16() + start, run.length() - start,
171                                                 run,
172                                                 font, offset));
173             offset += components->last().m_width;
174         }
175         offset += letterSpacing;
176     } else {
177         int start = 0;
178         for (int i = 0; i < run.length(); ++i) {
179             if (Font::treatAsSpace(run[i])) {
180                 if (i - start > 0) {
181                     components->append(TextRunComponent(run.characters16() + start, i - start,
182                                                         run,
183                                                         font, offset));
184                     offset += components->last().m_width;
185                 }
186                 int add = 0;
187                 if (numSpaces) {
188                     add = padding/numSpaces;
189                     padding -= add;
190                     --numSpaces;
191                 }
192                 components->append(TextRunComponent(1, font, offset));
193                 offset += add + components->last().m_width;
194                 if (i)
195                     offset += wordSpacing;
196                 start = i + 1;
197             }
198         }
199         if (run.length() - start > 0) {
200             components->append(TextRunComponent(run.characters16() + start, run.length() - start,
201                                                 run,
202                                                 font, offset));
203             offset += components->last().m_width;
204         }
205     }
206     return offset;
207 }
208
209 float Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, unsigned from, unsigned to) const
210 {
211     if (to < 0)
212         to = run.length();
213     if (from < 0)
214         from = 0;
215
216     TextRunComponents components;
217     int w = generateComponents(&components, *this, run);
218
219     float widthOfDrawnText = 0;
220     int curPos = 0;
221     for (int i = 0; i < (int)components.size(); ++i) {
222         const TextRunComponent& comp = components.at(i);
223         int len = comp.textLength();
224         int curEnd = curPos + len;
225         if (curPos < to && from < curEnd && !comp.isSpace()) {
226             FloatPoint pt = point;
227             if (run.rtl())
228                 pt.setX(point.x() + w - comp.m_offset - comp.m_width);
229             else
230                 pt.setX(point.x() + comp.m_offset);
231             widthOfDrawnText += drawSimpleText(context, comp.m_textRun, pt, from - curPos, std::min(to, curEnd) - curPos);
232         }
233         curPos += len;
234         if (from < curPos)
235             from = curPos;
236     }
237     return widthOfDrawnText;
238 }
239
240 void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, unsigned /* from */, unsigned /* to */) const
241 {
242     notImplemented();
243 }
244
245 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
246 {
247     TextRunComponents components;
248     int w = generateComponents(&components, *this, run);
249     return w;
250 }
251
252 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
253 {
254     // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
255     // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
256     int position = static_cast<int>(xFloat);
257
258     TextRunComponents components;
259     int w = generateComponents(&components, *this, run);
260
261     if (position >= w)
262         return run.length();
263
264     int offset = 0;
265     if (run.rtl()) {
266         for (size_t i = 0; i < components.size(); ++i) {
267             const TextRunComponent& comp = components.at(i);
268             int xe = w - comp.m_offset;
269             int xs = xe - comp.m_width;
270             if (position >= xs)
271                 return offset + (comp.isSpace()
272                     ? static_cast<int>((position - xe) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
273                     : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
274
275             offset += comp.textLength();
276         }
277     } else {
278         for (size_t i = 0; i < components.size(); ++i) {
279             const TextRunComponent& comp = components.at(i);
280             int xs = comp.m_offset;
281             int xe = xs + comp.m_width;
282             if (position <= xe) {
283                 if (position - xs >= xe)
284                     return offset + comp.textLength();
285                 return offset + (comp.isSpace()
286                     ? static_cast<int>((position - xs) * comp.m_spaces / std::max(1.f, comp.m_width) + 0.5)
287                     : offsetForPositionForSimpleText(comp.m_textRun, position - xs, includePartialGlyphs));
288             }
289             offset += comp.textLength();
290         }
291     }
292     return run.length();
293 }
294
295
296 static float cursorToX(const Font* font, const TextRunComponents& components, int width, bool rtl, int cursor)
297 {
298     int start = 0;
299     for (size_t i = 0; i < components.size(); ++i) {
300         const TextRunComponent& comp = components.at(i);
301         if (start + comp.textLength() <= cursor) {
302             start += comp.textLength();
303             continue;
304         }
305         int xs = comp.m_offset;
306         if (rtl)
307             xs = width - xs - comp.m_width;
308
309         int pos = cursor - start;
310         if (comp.isSpace()) {
311             if (rtl)
312                 pos = comp.textLength() - pos;
313             return xs + pos * comp.m_width / comp.m_spaces;
314         }
315         WidthIterator it(font, comp.m_textRun);
316         GlyphBuffer glyphBuffer;
317         it.advance(pos, &glyphBuffer);
318         return xs + it.m_runWidthSoFar;
319     }
320     return width;
321 }
322
323 FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt,
324     int h, unsigned from, unsigned to) const
325 {
326     TextRunComponents components;
327     int w = generateComponents(&components, *this, run);
328
329     if (!from && to == run.length())
330         return FloatRect(pt.x(), pt.y(), w, h);
331
332     float x1 = cursorToX(this, components, w, run.rtl(), from);
333     float x2 = cursorToX(this, components, w, run.rtl(), to);
334     if (x2 < x1)
335         std::swap(x1, x2);
336
337     return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
338 }
339
340 bool Font::canReturnFallbackFontsForComplexText()
341 {
342     return false;
343 }
344
345 bool Font::canExpandAroundIdeographsInComplexText()
346 {
347     return false;
348 }
349
350 } // namespace WebCore