15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
1702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/Font.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/NotImplemented.h"
3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/fonts/FontPlatformFeatures.h"
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/SimpleFontData.h"
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/harfbuzz/HarfBuzzShaper.h"
3819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#include "platform/fonts/GlyphBuffer.h"
391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
40a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkPaint.h"
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkTemplates.h"
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/unicode/Unicode.h"
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool FontPlatformFeatures::canReturnFallbackFontsForComplexText()
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static void paintGlyphs(GraphicsContext* gc, const SimpleFontData* font,
605d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    const Glyph* glyphs, unsigned numGlyphs,
6151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SkPoint* pos, const FloatRect& textRect)
6251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
63e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    TextDrawingModeFlags textMode = gc->textDrawingMode();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We draw text up to two times (once for fill, once for stroke).
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (textMode & TextModeFill) {
675d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        SkPaint paint = gc->fillPaint();
6819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        font->platformData().setupPaint(&paint, gc);
6981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        gc->adjustTextRenderMode(&paint);
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((textMode & TextModeStroke)
76e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        && gc->strokeStyle() != NoStroke
77e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        && gc->strokeThickness() > 0) {
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        SkPaint paint = gc->strokePaint();
8019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        font->platformData().setupPaint(&paint, gc);
8181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        gc->adjustTextRenderMode(&paint);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (textMode & TextModeFill) {
8507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // If there is a shadow and we filled above, there will already be
8607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // a shadow. We don't want to draw it again or it will be too dark
8707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // and it will go on top of the fill.
8807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            //
8907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // Note that this isn't strictly correct, since the stroke could be
9007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // very thick and the shadow wouldn't account for this. The "right"
9107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // thing would be to draw to a new layer and then draw that layer
9207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // with a shadow. But this is a lot of extra work for something
9307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            // that isn't normally an issue.
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paint.setLooper(0);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
9851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
9951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
10051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
10151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
10251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
10351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    const FloatPoint& point, const FloatRect& textRect) const
10451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
10551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SkScalar x = SkFloatToScalar(point.x());
10651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SkScalar y = SkFloatToScalar(point.y());
10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
10851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
10951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    SkPoint* pos = storage.get();
11051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
11151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    const OpenTypeVerticalData* verticalData = font->verticalData();
11251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (font->platformData().orientation() == Vertical && verticalData) {
11351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        AffineTransform savedMatrix = gc->getCTM();
11451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
11551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));
11651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
11751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        const unsigned kMaxBufferLength = 256;
11851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        Vector<FloatPoint, kMaxBufferLength> translations;
11951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
12051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        const FontMetrics& metrics = font->fontMetrics();
12151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline));
12251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        float horizontalOffset = point.x();
12351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
12451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        unsigned glyphIndex = 0;
12551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        while (glyphIndex < numGlyphs) {
12651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
12751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
1285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
12951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            translations.resize(chunkLength);
13051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chunkLength, reinterpret_cast<float*>(&translations[0]));
13151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
13251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            x = verticalOriginX;
13351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            y = SkFloatToScalar(point.y() + horizontalOffset - point.x());
13451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
13551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            float currentWidth = 0;
13651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) {
13751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                pos[i].set(
13851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                    x + SkIntToScalar(lroundf(translations[i].x())),
13951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                    y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y())));
140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width();
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
14251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            horizontalOffset += currentWidth;
14351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect);
14451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
14551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
14651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        gc->setCTM(savedMatrix);
14751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
14951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
15051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // FIXME: text rendering speed:
15151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Android has code in their WebCore fork to special case when the
15251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // GlyphBuffer has no advances other than the defaults. In that case the
15351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // text drawing can proceed faster. However, it's unclear when those
15451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // patches may be upstreamed to WebKit so we always use the slower path
15551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // here.
1565d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    const FloatSize* adv = glyphBuffer.advances(from);
15751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (unsigned i = 0; i < numGlyphs; i++) {
15851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        pos[i].set(x, y);
15951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        x += SkFloatToScalar(adv[i].width());
16051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        y += SkFloatToScalar(adv[i].height());
16151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
16251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
1635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    const Glyph* glyphs = glyphBuffer.glyphs(from);
16451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect);
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
16993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (!runInfo.run.length())
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
172e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    TextDrawingModeFlags textMode = gc->textDrawingMode();
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool fill = textMode & TextModeFill;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool stroke = (textMode & TextModeStroke)
175e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        && gc->strokeStyle() != NoStroke
176e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        && gc->strokeThickness() > 0;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!fill && !stroke)
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GlyphBuffer glyphBuffer;
18293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    HarfBuzzShaper shaper(this, runInfo.run);
18393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    shaper.setDrawRange(runInfo.from, runInfo.to);
184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty())
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint adjustedPoint = shaper.adjustStartPoint(point);
18793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    GlyphBuffer glyphBuffer;
193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
194a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuffer, ForTextEmphasis);
195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
196d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (glyphBuffer.isEmpty())
197d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
198d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
199d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
200d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
201d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
202a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochfloat Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
204a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis);
205a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    shaper.setDrawRange(runInfo.from, runInfo.to);
206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    shaper.shape(&glyphBuffer);
207d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return 0;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
210d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, IntRectExtent* glyphBounds) const
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HarfBuzzShaper shaper(this, run);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!shaper.shape())
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
21543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
216d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top()));
217d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom()));
218d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left())));
219d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right() - shaper.totalWidth())));
220d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return shaper.totalWidth();
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Return the code point index for the given |x| offset into the text run.
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          bool includePartialGlyphs) const
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HarfBuzzShaper shaper(this, run);
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!shaper.shape())
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return shaper.offsetForPosition(xFloat);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Return the rectangle for selecting the given range of code-points in the TextRun.
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatRect Font::selectionRectForComplexText(const TextRun& run,
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                            const FloatPoint& point, int height,
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                            int from, int to) const
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HarfBuzzShaper shaper(this, run);
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!shaper.shape())
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return FloatRect();
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return shaper.selectionRect(point, height, from, to);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
246