Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (c) 2011 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "platform/fonts/Font.h"
     33 
     34 #include "platform/LayoutTestSupport.h"
     35 #include "platform/fonts/FontPlatformFeatures.h"
     36 #include "platform/fonts/FontSmoothingMode.h"
     37 #include "platform/fonts/GlyphBuffer.h"
     38 #include "platform/fonts/SimpleFontData.h"
     39 #include "platform/graphics/GraphicsContext.h"
     40 
     41 #include "third_party/skia/include/core/SkCanvas.h"
     42 #include "third_party/skia/include/core/SkPaint.h"
     43 #include "third_party/skia/include/core/SkTypeface.h"
     44 
     45 namespace blink {
     46 
     47 bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
     48 {
     49     return true;
     50 }
     51 
     52 static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Font* font, bool shouldAntialias, bool shouldSmoothFonts)
     53 {
     54     const FontPlatformData& platformData = fontData->platformData();
     55     const float textSize = platformData.m_textSize >= 0 ? platformData.m_textSize : 12;
     56 
     57     paint->setAntiAlias(shouldAntialias);
     58     paint->setEmbeddedBitmapText(false);
     59     paint->setTextSize(SkFloatToScalar(textSize));
     60     paint->setVerticalText(platformData.orientation() == Vertical);
     61     paint->setTypeface(platformData.typeface());
     62     paint->setFakeBoldText(platformData.m_syntheticBold);
     63     paint->setTextSkewX(platformData.m_syntheticItalic ? -SK_Scalar1 / 4 : 0);
     64     paint->setAutohinted(false); // freetype specific
     65     paint->setLCDRenderText(shouldSmoothFonts);
     66     paint->setSubpixelText(true);
     67 
     68     // When using CoreGraphics, disable hinting when webkit-font-smoothing:antialiased is used.
     69     // See crbug.com/152304
     70     if (font->fontDescription().fontSmoothing() == Antialiased || font->fontDescription().textRendering() == GeometricPrecision)
     71         paint->setHinting(SkPaint::kNo_Hinting);
     72 }
     73 
     74 // TODO: This needs to be split into helper functions to better scope the
     75 // inputs/outputs, and reduce duplicate code.
     76 // This issue is tracked in https://bugs.webkit.org/show_bug.cgi?id=62989
     77 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
     78     const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
     79     const FloatPoint& point, const FloatRect& textRect) const
     80 {
     81     bool shouldSmoothFonts = true;
     82     bool shouldAntialias = true;
     83 
     84     switch (fontDescription().fontSmoothing()) {
     85     case Antialiased:
     86         shouldSmoothFonts = false;
     87         break;
     88     case SubpixelAntialiased:
     89         break;
     90     case NoSmoothing:
     91         shouldAntialias = false;
     92         shouldSmoothFonts = false;
     93         break;
     94     case AutoSmoothing:
     95         // For the AutoSmooth case, don't do anything! Keep the default settings.
     96         break;
     97     }
     98 
     99     if (LayoutTestSupport::isRunningLayoutTest()) {
    100         shouldSmoothFonts = false;
    101         shouldAntialias = shouldAntialias && LayoutTestSupport::isFontAntialiasingEnabledForTest();
    102     }
    103 
    104     const Glyph* glyphs = glyphBuffer.glyphs(from);
    105     SkScalar x = SkFloatToScalar(point.x());
    106     SkScalar y = SkFloatToScalar(point.y());
    107 
    108     if (font->platformData().orientation() == Vertical)
    109         y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
    110 
    111     // FIXME: implement a no-vertical-advances fast path like FontHarfBuzz has.
    112 
    113     // FIXME: text rendering speed:
    114     // Android has code in their WebCore fork to special case when the
    115     // GlyphBuffer has no advances other than the defaults. In that case the
    116     // text drawing can proceed faster. However, it's unclear when those
    117     // patches may be upstreamed to WebKit so we always use the slower path
    118     // here.
    119     const FloatSize* adv = glyphBuffer.advances(from);
    120     SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
    121     SkPoint* pos = storage.get();
    122 
    123     for (unsigned i = 0; i < numGlyphs; i++) {
    124         pos[i].set(x, y);
    125         x += SkFloatToScalar(adv[i].width());
    126         y += SkFloatToScalar(adv[i].height());
    127     }
    128 
    129     if (font->platformData().orientation() == Vertical) {
    130         gc->save();
    131         gc->rotate(-0.5 * SK_ScalarPI);
    132         SkMatrix rotator;
    133         rotator.reset();
    134         rotator.setRotate(90);
    135         rotator.mapPoints(pos, numGlyphs);
    136     }
    137     TextDrawingModeFlags textMode = gc->textDrawingMode();
    138 
    139     // We draw text up to two times (once for fill, once for stroke).
    140     if (textMode & TextModeFill) {
    141         SkPaint paint = gc->fillPaint();
    142         setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
    143         gc->adjustTextRenderMode(&paint);
    144         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    145 
    146         gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
    147     }
    148 
    149     if ((textMode & TextModeStroke)
    150         && gc->strokeStyle() != NoStroke
    151         && gc->strokeThickness() > 0) {
    152 
    153         SkPaint paint = gc->strokePaint();
    154         setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
    155         gc->adjustTextRenderMode(&paint);
    156         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    157 
    158         if (textMode & TextModeFill) {
    159             // If we also filled, we don't want to draw shadows twice.
    160             // See comment in FontHarfBuzz.cpp::paintGlyphs() for more details.
    161             paint.setLooper(0);
    162         }
    163 
    164         gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
    165     }
    166     if (font->platformData().orientation() == Vertical)
    167         gc->restore();
    168 }
    169 
    170 void Font::drawTextBlob(GraphicsContext*, const SkTextBlob*, const SkPoint&) const
    171 {
    172     // FIXME: Add text blob support to FontMac.
    173 }
    174 
    175 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initialAdvance,
    176     const FloatRect& bounds, float& advance, bool couldUseLCD) const
    177 {
    178     // FIXME: Add text blob support to FontMac.
    179     return nullptr;
    180 }
    181 
    182 } // namespace blink
    183