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 WebCore {
     46 
     47 bool FontPlatformFeatures::canReturnFallbackFontsForComplexText()
     48 {
     49     return true;
     50 }
     51 
     52 bool FontPlatformFeatures::canExpandAroundIdeographsInComplexText()
     53 {
     54     return true;
     55 }
     56 
     57 static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Font* font, bool shouldAntialias, bool shouldSmoothFonts)
     58 {
     59     const FontPlatformData& platformData = fontData->platformData();
     60     const float textSize = platformData.m_size >= 0 ? platformData.m_size : 12;
     61 
     62     paint->setAntiAlias(shouldAntialias);
     63     paint->setEmbeddedBitmapText(false);
     64     paint->setTextSize(SkFloatToScalar(textSize));
     65     paint->setVerticalText(platformData.orientation() == Vertical);
     66     paint->setTypeface(platformData.typeface());
     67     paint->setFakeBoldText(platformData.m_syntheticBold);
     68     paint->setTextSkewX(platformData.m_syntheticOblique ? -SK_Scalar1 / 4 : 0);
     69     paint->setAutohinted(false); // freetype specific
     70     paint->setLCDRenderText(shouldSmoothFonts);
     71     paint->setSubpixelText(true);
     72 
     73     // When using CoreGraphics, disable hinting when webkit-font-smoothing:antialiased is used.
     74     // See crbug.com/152304
     75     if (font->fontDescription().fontSmoothing() == Antialiased || font->fontDescription().textRendering() == GeometricPrecision)
     76         paint->setHinting(SkPaint::kNo_Hinting);
     77 }
     78 
     79 // TODO: This needs to be split into helper functions to better scope the
     80 // inputs/outputs, and reduce duplicate code.
     81 // This issue is tracked in https://bugs.webkit.org/show_bug.cgi?id=62989
     82 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
     83     const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs,
     84     const FloatPoint& point, const FloatRect& textRect) const
     85 {
     86     bool shouldSmoothFonts = true;
     87     bool shouldAntialias = true;
     88 
     89     switch (fontDescription().fontSmoothing()) {
     90     case Antialiased:
     91         shouldSmoothFonts = false;
     92         break;
     93     case SubpixelAntialiased:
     94         break;
     95     case NoSmoothing:
     96         shouldAntialias = false;
     97         shouldSmoothFonts = false;
     98         break;
     99     case AutoSmoothing:
    100         // For the AutoSmooth case, don't do anything! Keep the default settings.
    101         break;
    102     }
    103 
    104     if (isRunningLayoutTest()) {
    105         shouldSmoothFonts = false;
    106         shouldAntialias = shouldAntialias && isFontAntialiasingEnabledForTest();
    107     }
    108 
    109     const Glyph* glyphs = glyphBuffer.glyphs(from);
    110     SkScalar x = SkFloatToScalar(point.x());
    111     SkScalar y = SkFloatToScalar(point.y());
    112 
    113     if (font->platformData().orientation() == Vertical)
    114         y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
    115     // FIXME: text rendering speed:
    116     // Android has code in their WebCore fork to special case when the
    117     // GlyphBuffer has no advances other than the defaults. In that case the
    118     // text drawing can proceed faster. However, it's unclear when those
    119     // patches may be upstreamed to WebKit so we always use the slower path
    120     // here.
    121     const FloatSize* adv = glyphBuffer.advances(from);
    122     SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
    123     SkPoint* pos = storage.get();
    124 
    125     for (unsigned i = 0; i < numGlyphs; i++) {
    126         pos[i].set(x, y);
    127         x += SkFloatToScalar(adv[i].width());
    128         y += SkFloatToScalar(adv[i].height());
    129     }
    130 
    131     if (font->platformData().orientation() == Vertical) {
    132         gc->save();
    133         gc->rotate(-0.5 * SK_ScalarPI);
    134         SkMatrix rotator;
    135         rotator.reset();
    136         rotator.setRotate(90);
    137         rotator.mapPoints(pos, numGlyphs);
    138     }
    139     TextDrawingModeFlags textMode = gc->textDrawingMode();
    140 
    141     // We draw text up to two times (once for fill, once for stroke).
    142     if (textMode & TextModeFill) {
    143         SkPaint paint = gc->fillPaint();
    144         setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
    145         gc->adjustTextRenderMode(&paint);
    146         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    147 
    148         gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
    149     }
    150 
    151     if ((textMode & TextModeStroke)
    152         && gc->strokeStyle() != NoStroke
    153         && gc->strokeThickness() > 0) {
    154 
    155         SkPaint paint = gc->strokePaint();
    156         setupPaint(&paint, font, this, shouldAntialias, shouldSmoothFonts);
    157         gc->adjustTextRenderMode(&paint);
    158         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    159 
    160         if (textMode & TextModeFill) {
    161             // If we also filled, we don't want to draw shadows twice.
    162             // See comment in FontHarfBuzz.cpp::paintGlyphs() for more details.
    163             paint.setLooper(0);
    164         }
    165 
    166         gc->drawPosText(glyphs, numGlyphs * sizeof(Glyph), pos, textRect, paint);
    167     }
    168     if (font->platformData().orientation() == Vertical)
    169         gc->restore();
    170 }
    171 
    172 } // namespace WebCore
    173