Reland patch ensure font load before calling Skia during printing
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / FontChromiumWin.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Computer, Inc.
3  * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  * 
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  * 
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "Font.h"
34
35 #include "FontFallbackList.h"
36 #include "GlyphBuffer.h"
37 #include "NotImplemented.h"
38 #include "PlatformSupport.h"
39 #include "PlatformContextSkia.h"
40 #include "SimpleFontData.h"
41 #include "SkiaFontWin.h"
42 #include "UniscribeHelperTextRun.h"
43
44 #if !USE(SKIA_TEXT)
45 #include "TransparencyWin.h"
46 #include "skia/ext/skia_utils_win.h"
47 #endif
48
49 #include <windows.h>
50
51 using namespace std;
52
53 namespace WebCore {
54
55 #if !USE(SKIA_TEXT)
56 namespace {
57
58 bool canvasHasMultipleLayers(const SkCanvas* canvas)
59 {
60     SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
61     iter.next(); // There is always at least one layer.
62     return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
63 }
64
65 class TransparencyAwareFontPainter {
66 public:
67     TransparencyAwareFontPainter(GraphicsContext*, const FloatPoint&);
68     ~TransparencyAwareFontPainter();
69
70 protected:
71     // Called by our subclass' constructor to initialize GDI if necessary. This
72     // is a separate function so it can be called after the subclass finishes
73     // construction (it calls virtual functions).
74     void init();
75
76     virtual IntRect estimateTextBounds() = 0;
77
78     // Use the context from the transparency helper when drawing with GDI. It
79     // may point to a temporary one.
80     GraphicsContext* m_graphicsContext;
81     PlatformGraphicsContext* m_platformContext;
82
83     FloatPoint m_point;
84
85     // Set when Windows can handle the type of drawing we're doing.
86     bool m_useGDI;
87
88     // These members are valid only when m_useGDI is set.
89     HDC m_hdc;
90     TransparencyWin m_transparency;
91
92 private:
93     // Call when we're using GDI mode to initialize the TransparencyWin to help
94     // us draw GDI text.
95     void initializeForGDI();
96
97     bool m_createdTransparencyLayer; // We created a layer to give the font some alpha.
98 };
99
100 TransparencyAwareFontPainter::TransparencyAwareFontPainter(GraphicsContext* context,
101                                                            const FloatPoint& point)
102     : m_graphicsContext(context)
103     , m_platformContext(context->platformContext())
104     , m_point(point)
105     , m_useGDI(windowsCanHandleTextDrawing(context))
106     , m_hdc(0)
107     , m_createdTransparencyLayer(false)
108 {
109 }
110
111 void TransparencyAwareFontPainter::init()
112 {
113     if (m_useGDI)
114         initializeForGDI();
115 }
116
117 void TransparencyAwareFontPainter::initializeForGDI()
118 {
119     m_graphicsContext->save();
120     SkColor color = m_platformContext->effectiveFillColor();
121     // Used only when m_createdTransparencyLayer is true.
122     float layerAlpha = 0.0f;
123     if (SkColorGetA(color) != 0xFF) {
124         // When the font has some transparency, apply it by creating a new
125         // transparency layer with that opacity applied. We'll actually create
126         // a new transparency layer after we calculate the bounding box.
127         m_createdTransparencyLayer = true;
128         layerAlpha = SkColorGetA(color) / 255.0f;
129         // The color should be opaque now.
130         color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
131     }
132
133     TransparencyWin::LayerMode layerMode;
134     IntRect layerRect;
135     if (m_platformContext->isDrawingToImageBuffer()) {
136         // Assume if we're drawing to an image buffer that the background
137         // is not opaque and we have to undo ClearType. We may want to
138         // enhance this to actually check, since it will often be opaque
139         // and we could do ClearType in that case.
140         layerMode = TransparencyWin::TextComposite;
141         layerRect = estimateTextBounds();
142         m_graphicsContext->clip(layerRect);
143         if (m_createdTransparencyLayer)
144             m_graphicsContext->beginTransparencyLayer(layerAlpha);
145
146         // The transparency helper requires that we draw text in black in
147         // this mode and it will apply the color.
148         m_transparency.setTextCompositeColor(color);
149         color = SkColorSetRGB(0, 0, 0);
150     } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
151         // When we're drawing a web page, we know the background is opaque,
152         // but if we're drawing to a layer, we still need extra work.
153         layerMode = TransparencyWin::OpaqueCompositeLayer;
154         layerRect = estimateTextBounds();
155         m_graphicsContext->clip(layerRect);
156         if (m_createdTransparencyLayer)
157             m_graphicsContext->beginTransparencyLayer(layerAlpha);
158     } else {
159         // Common case of drawing onto the bottom layer of a web page: we
160         // know everything is opaque so don't need to do anything special.
161         layerMode = TransparencyWin::NoLayer;
162     }
163
164     // Bug 26088 - init() might fail if layerRect is invalid. Given this, we
165     // need to be careful to check for null pointers everywhere after this call
166     m_transparency.init(m_graphicsContext, layerMode, 
167                         TransparencyWin::KeepTransform, layerRect);
168
169     // Set up the DC, using the one from the transparency helper.
170     if (m_transparency.platformContext()) {
171         m_hdc = skia::BeginPlatformPaint(m_transparency.platformContext()->canvas());
172         SetTextColor(m_hdc, skia::SkColorToCOLORREF(color));
173         SetBkMode(m_hdc, TRANSPARENT);
174     }
175 }
176
177 TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
178 {
179     if (!m_useGDI || !m_graphicsContext || !m_platformContext)
180         return;
181     m_transparency.composite();
182     if (m_createdTransparencyLayer)
183         m_graphicsContext->endTransparencyLayer();
184     m_graphicsContext->restore();
185     if (m_transparency.platformContext())
186         skia::EndPlatformPaint(m_transparency.platformContext()->canvas());
187 }
188
189 // Specialization for simple GlyphBuffer painting.
190 class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
191  public:
192     TransparencyAwareGlyphPainter(GraphicsContext*,
193                                   const SimpleFontData*,
194                                   const GlyphBuffer&,
195                                   int from, int numGlyphs,
196                                   const FloatPoint&);
197     ~TransparencyAwareGlyphPainter();
198
199     // Draws the partial string of glyphs, starting at |startAdvance| to the
200     // left of m_point. We express it this way so that if we're using the Skia
201     // drawing path we can use floating-point positioning, even though we have
202     // to use integer positioning in the GDI path.
203     bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, float startAdvance) const;
204
205  private:
206     virtual IntRect estimateTextBounds();
207
208     const SimpleFontData* m_font;
209     const GlyphBuffer& m_glyphBuffer;
210     int m_from;
211     int m_numGlyphs;
212
213     // When m_useGdi is set, this stores the previous HFONT selected into the
214     // m_hdc so we can restore it.
215     HGDIOBJ m_oldFont; // For restoring the DC to its original state.
216 };
217
218 TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter(
219     GraphicsContext* context,
220     const SimpleFontData* font,
221     const GlyphBuffer& glyphBuffer,
222     int from, int numGlyphs,
223     const FloatPoint& point)
224     : TransparencyAwareFontPainter(context, point)
225     , m_font(font)
226     , m_glyphBuffer(glyphBuffer)
227     , m_from(from)
228     , m_numGlyphs(numGlyphs)
229     , m_oldFont(0)
230 {
231     init();
232
233     if (m_hdc)
234         m_oldFont = ::SelectObject(m_hdc, m_font->platformData().hfont());
235 }
236
237 TransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter()
238 {
239     if (m_useGDI && m_hdc)
240         ::SelectObject(m_hdc, m_oldFont);
241 }
242
243
244 // Estimates the bounding box of the given text. This is copied from
245 // FontCGWin.cpp, it is possible, but a lot more work, to get the precide
246 // bounds.
247 IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
248 {
249     int totalWidth = 0;
250     for (int i = 0; i < m_numGlyphs; i++)
251         totalWidth += lroundf(m_glyphBuffer.advanceAt(m_from + i));
252
253     const FontMetrics& fontMetrics = m_font->fontMetrics();
254     return IntRect(m_point.x() - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
255                    m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
256                    totalWidth + fontMetrics.ascent() + fontMetrics.descent(),
257                    fontMetrics.lineSpacing()); 
258 }
259
260 bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
261                                                const WORD* glyphs,
262                                                const int* advances,
263                                                float startAdvance) const
264 {
265     if (!m_useGDI) {
266         SkPoint origin = m_point;
267         origin.fX += SkFloatToScalar(startAdvance);
268         paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
269                       numGlyphs, glyphs, advances, 0, &origin);
270         return true;
271     }
272
273     if (!m_graphicsContext || !m_hdc)
274         return true;
275
276     // Windows' origin is the top-left of the bounding box, so we have
277     // to subtract off the font ascent to get it.
278     int x = lroundf(m_point.x() + startAdvance);
279     int y = lroundf(m_point.y() - m_font->fontMetrics().ascent());
280
281     // If there is a non-blur shadow and both the fill color and shadow color 
282     // are opaque, handle without skia. 
283     FloatSize shadowOffset;
284     float shadowBlur;
285     Color shadowColor;
286     ColorSpace shadowColorSpace;
287     if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
288         // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
289         // will have already returned true during the ctor initiatization of m_useGDI
290         ASSERT(shadowColor.alpha() == 255);
291         ASSERT(m_graphicsContext->fillColor().alpha() == 255);
292         ASSERT(!shadowBlur);
293         COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
294         COLORREF savedTextColor = GetTextColor(m_hdc);
295         SetTextColor(m_hdc, textColor);
296         ExtTextOut(m_hdc, x + shadowOffset.width(), y + shadowOffset.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
297         SetTextColor(m_hdc, savedTextColor);
298     }
299     
300     return !!ExtTextOut(m_hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
301 }
302
303 class TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
304  public:
305     TransparencyAwareUniscribePainter(GraphicsContext*,
306                                       const Font*,
307                                       const TextRun&,
308                                       int from, int to,
309                                       const FloatPoint&);
310     ~TransparencyAwareUniscribePainter();
311
312     // Uniscibe will draw directly into our buffer, so we need to expose our DC.
313     HDC hdc() const { return m_hdc; }
314
315  private:
316     virtual IntRect estimateTextBounds();
317
318     const Font* m_font;
319     const TextRun& m_run;
320     int m_from;
321     int m_to;
322 };
323
324 TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter(
325     GraphicsContext* context,
326     const Font* font,
327     const TextRun& run,
328     int from, int to,
329     const FloatPoint& point)
330     : TransparencyAwareFontPainter(context, point)
331     , m_font(font)
332     , m_run(run)
333     , m_from(from)
334     , m_to(to)
335 {
336     init();
337 }
338
339 TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter()
340 {
341 }
342
343 IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
344 {
345     // This case really really sucks. There is no convenient way to estimate
346     // the bounding box. So we run Uniscribe twice. If we find this happens a
347     // lot, the way to fix it is to make the extra layer after the
348     // UniscribeHelper has measured the text.
349     IntPoint intPoint(lroundf(m_point.x()),
350                       lroundf(m_point.y()));
351
352     UniscribeHelperTextRun state(m_run, *m_font);
353     int left = lroundf(m_point.x()) + state.characterToX(m_from);
354     int right = lroundf(m_point.x()) + state.characterToX(m_to);
355     
356     // Adjust for RTL script since we just want to know the text bounds.
357     if (left > right)
358         std::swap(left, right);
359
360     // This algorithm for estimating how much extra space we need (the text may
361     // go outside the selection rect) is based roughly on
362     // TransparencyAwareGlyphPainter::estimateTextBounds above.
363     const FontMetrics& fontMetrics = m_font->fontMetrics();
364     return IntRect(left - (fontMetrics.ascent() + fontMetrics.descent()) / 2,
365                    m_point.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
366                    (right - left) + fontMetrics.ascent() + fontMetrics.descent(),
367                    fontMetrics.lineSpacing());
368 }
369
370 } // namespace
371 #endif
372
373 bool Font::canReturnFallbackFontsForComplexText()
374 {
375     return false;
376 }
377
378 bool Font::canExpandAroundIdeographsInComplexText()
379 {
380     return false;
381 }
382
383 #if USE(SKIA_TEXT)
384 void Font::drawGlyphs(GraphicsContext* graphicsContext,
385                       const SimpleFontData* font,
386                       const GlyphBuffer& glyphBuffer,
387                       int from,
388                       int numGlyphs,
389                       const FloatPoint& point) const
390 {
391     SkColor color = graphicsContext->platformContext()->effectiveFillColor();
392     unsigned char alpha = SkColorGetA(color);
393     // Skip 100% transparent text; no need to draw anything.
394     if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
395         return;
396
397     HFONT hfont = font->platformData().hfont();
398
399     // We draw the glyphs in chunks to avoid having to do a heap allocation for
400     // the arrays of characters and advances.
401     const int kMaxBufferLength = 256;
402     Vector<WORD, kMaxBufferLength> glyphs;
403     Vector<int, kMaxBufferLength> advances;
404     int glyphIndex = 0;  // The starting glyph of the current chunk.
405
406     // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
407     // of each glyph in floating point units and rounds to integer advances at the last possible moment.
408
409     float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
410     int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
411     while (glyphIndex < numGlyphs) {
412         // How many chars will be in this chunk?
413         int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
414         glyphs.resize(curLen);
415         advances.resize(curLen);
416
417         float currentWidth = 0;
418         for (int i = 0; i < curLen; ++i, ++glyphIndex) {
419             glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
420             horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
421             advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
422             lastHorizontalOffsetRounded += advances[i];
423             currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
424             
425             // Bug 26088 - very large positive or negative runs can fail to
426             // render so we clamp the size here. In the specs, negative
427             // letter-spacing is implementation-defined, so this should be
428             // fine, and it matches Safari's implementation. The call actually
429             // seems to crash if kMaxNegativeRun is set to somewhere around
430             // -32830, so we give ourselves a little breathing room.
431             const int maxNegativeRun = -32768;
432             const int maxPositiveRun =  32768;
433             if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) 
434                 advances[i] = 0;
435         }
436
437         SkPoint origin = point;
438         origin.fX += SkFloatToScalar(horizontalOffset - point.x() - currentWidth);
439         paintSkiaText(graphicsContext, hfont, curLen, &glyphs[0], &advances[0], 0, &origin);
440     }
441 }
442 #else
443 static void drawGlyphsWin(GraphicsContext* graphicsContext,
444                           const SimpleFontData* font,
445                           const GlyphBuffer& glyphBuffer,
446                           int from,
447                           int numGlyphs,
448                           const FloatPoint& point) {
449     TransparencyAwareGlyphPainter painter(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
450
451     // We draw the glyphs in chunks to avoid having to do a heap allocation for
452     // the arrays of characters and advances. Since ExtTextOut is the
453     // lowest-level text output function on Windows, there should be little
454     // penalty for splitting up the text. On the other hand, the buffer cannot
455     // be bigger than 4094 or the function will fail.
456     const int kMaxBufferLength = 256;
457     Vector<WORD, kMaxBufferLength> glyphs;
458     Vector<int, kMaxBufferLength> advances;
459     int glyphIndex = 0; // The starting glyph of the current chunk.
460
461     // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
462     // of each glyph in floating point units and rounds to integer advances at the last possible moment.
463
464     float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
465     int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
466     while (glyphIndex < numGlyphs) {
467         // How many chars will be in this chunk?
468         int curLen = min(kMaxBufferLength, numGlyphs - glyphIndex);
469         glyphs.resize(curLen);
470         advances.resize(curLen);
471
472         float currentWidth = 0;
473         for (int i = 0; i < curLen; ++i, ++glyphIndex) {
474             glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
475             horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
476             advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
477             lastHorizontalOffsetRounded += advances[i];
478             currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
479             
480             // Bug 26088 - very large positive or negative runs can fail to
481             // render so we clamp the size here. In the specs, negative
482             // letter-spacing is implementation-defined, so this should be
483             // fine, and it matches Safari's implementation. The call actually
484             // seems to crash if kMaxNegativeRun is set to somewhere around
485             // -32830, so we give ourselves a little breathing room.
486             const int maxNegativeRun = -32768;
487             const int maxPositiveRun =  32768;
488             if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) 
489                 advances[i] = 0;
490         }
491
492         // Actually draw the glyphs (with retry on failure).
493         bool success = false;
494         for (int executions = 0; executions < 2; ++executions) {
495             success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], horizontalOffset - point.x() - currentWidth);
496             if (!success && !executions) {
497                 // Ask the browser to load the font for us and retry.
498                 PlatformSupport::ensureFontLoaded(font->platformData().hfont());
499                 continue;
500             }
501             break;
502         }
503
504         if (!success)
505             LOG_ERROR("Unable to draw the glyphs after second attempt");
506     }
507 }
508
509 void Font::drawGlyphs(GraphicsContext* graphicsContext,
510                       const SimpleFontData* font,
511                       const GlyphBuffer& glyphBuffer,
512                       int from,
513                       int numGlyphs,
514                       const FloatPoint& point) const
515 {
516     SkColor color = graphicsContext->platformContext()->effectiveFillColor();
517     unsigned char alpha = SkColorGetA(color);
518     // Skip 100% transparent text; no need to draw anything.
519     if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
520         return;
521     if (!alpha || windowsCanHandleDrawTextShadow(graphicsContext) || !windowsCanHandleTextDrawingWithoutShadow(graphicsContext)) {
522         drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
523         return;
524     }
525     // Draw in two passes: skia for the shadow, GDI for foreground text
526     // pass1: shadow (will use skia)
527     graphicsContext->save();
528     graphicsContext->setFillColor(Color::transparent, graphicsContext->fillColorSpace());
529     drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
530     graphicsContext->restore();
531     // pass2: foreground text (will use GDI)
532     FloatSize shadowOffset;
533     float shadowBlur;
534     Color shadowColor;
535     ColorSpace shadowColorSpace;
536     graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
537     graphicsContext->setShadow(shadowOffset, shadowBlur, Color::transparent, shadowColorSpace);
538     drawGlyphsWin(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
539     graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
540 }
541 #endif
542
543 FloatRect Font::selectionRectForComplexText(const TextRun& run,
544                                             const FloatPoint& point,
545                                             int h,
546                                             int from,
547                                             int to) const
548 {
549     UniscribeHelperTextRun state(run, *this);
550     float left = static_cast<float>(point.x() + state.characterToX(from));
551     float right = static_cast<float>(point.x() + state.characterToX(to));
552
553     // If the text is RTL, left will actually be after right.
554     if (left < right)
555         return FloatRect(left, point.y(),
556                        right - left, static_cast<float>(h));
557
558     return FloatRect(right, point.y(),
559                      left - right, static_cast<float>(h));
560 }
561
562 void Font::drawComplexText(GraphicsContext* graphicsContext,
563                            const TextRun& run,
564                            const FloatPoint& point,
565                            int from,
566                            int to) const
567 {
568     PlatformGraphicsContext* context = graphicsContext->platformContext();
569     UniscribeHelperTextRun state(run, *this);
570
571     SkColor color = graphicsContext->platformContext()->effectiveFillColor();
572     unsigned char alpha = SkColorGetA(color);
573     // Skip 100% transparent text; no need to draw anything.
574     if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
575         return;
576
577 #if USE(SKIA_TEXT)
578     HDC hdc = 0;
579 #else
580     TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
581
582     HDC hdc = painter.hdc();
583     if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
584         return;
585
586     // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
587     // Enforce non-transparent color.
588     color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
589     if (hdc) {
590         SetTextColor(hdc, skia::SkColorToCOLORREF(color));
591         SetBkMode(hdc, TRANSPARENT);
592     }
593
594     // If there is a non-blur shadow and both the fill color and shadow color 
595     // are opaque, handle without skia. 
596     FloatSize shadowOffset;
597     float shadowBlur;
598     Color shadowColor;
599     ColorSpace shadowColorSpace;
600     if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
601         COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
602         COLORREF savedTextColor = GetTextColor(hdc);
603         SetTextColor(hdc, textColor);
604         state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(),
605                    static_cast<int>(point.y() - fontMetrics().ascent()) + shadowOffset.height(), from, to);
606         SetTextColor(hdc, savedTextColor); 
607     }
608 #endif
609     // Uniscribe counts the coordinates from the upper left, while WebKit uses
610     // the baseline, so we have to subtract off the ascent.
611     state.draw(graphicsContext, hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), from, to);
612 }
613
614 void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
615 {
616     notImplemented();
617 }
618
619 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
620 {
621     UniscribeHelperTextRun state(run, *this);
622     return static_cast<float>(state.width());
623 }
624
625 int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
626                                           bool includePartialGlyphs) const
627 {
628     // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
629     // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
630     int x = static_cast<int>(xFloat);
631
632     // Mac code ignores includePartialGlyphs, and they don't know what it's
633     // supposed to do, so we just ignore it as well.
634     UniscribeHelperTextRun state(run, *this);
635     int charIndex = state.xToCharacter(x);
636
637     // XToCharacter will return -1 if the position is before the first
638     // character (we get called like this sometimes).
639     if (charIndex < 0)
640         charIndex = 0;
641     return charIndex;
642 }
643
644 } // namespace WebCore