Home | History | Annotate | Download | only in skia
      1 /*
      2  * Copyright (c) 2008, 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/skia/SkiaFontWin.h"
     33 
     34 #include "platform/fonts/SimpleFontData.h"
     35 #include "platform/fonts/win/FontPlatformDataWin.h"
     36 #include "platform/graphics/Gradient.h"
     37 #include "platform/graphics/GraphicsContext.h"
     38 #include "platform/graphics/Pattern.h"
     39 #include "platform/transforms/AffineTransform.h"
     40 #include "third_party/skia/include/core/SkCanvas.h"
     41 #include "third_party/skia/include/core/SkDevice.h"
     42 #include "third_party/skia/include/core/SkPaint.h"
     43 #include "third_party/skia/include/core/SkShader.h"
     44 #include "third_party/skia/include/core/SkTemplates.h"
     45 #include "wtf/RefPtr.h"
     46 
     47 namespace WebCore {
     48 
     49 static void skiaDrawText(GraphicsContext* context,
     50     const SkPoint& point,
     51     const SkRect& textRect,
     52     SkPaint* paint,
     53     const WORD* glyphs,
     54     const int* advances,
     55     const GOFFSET* offsets,
     56     unsigned numGlyphs)
     57 {
     58     // Reserve space for 64 SkPoints on the stack. If numGlyphs is larger, the array
     59     // will dynamically allocate it space for numGlyph glyphs. This is used to store
     60     // the computed x,y locations. In the case where offsets==null, then we use it
     61     // to store (twice as many) SkScalars for x[]
     62     static const size_t kLocalGlyphMax = 64;
     63 
     64     SkScalar x = point.fX;
     65     SkScalar y = point.fY;
     66     if (offsets) {
     67         SkAutoSTArray<kLocalGlyphMax, SkPoint> storage(numGlyphs);
     68         SkPoint* pos = storage.get();
     69         for (unsigned i = 0; i < numGlyphs; i++) {
     70             // GDI has dv go up, so we negate it
     71             pos[i].set(x + SkIntToScalar(offsets[i].du),
     72                        y + -SkIntToScalar(offsets[i].dv));
     73             x += SkIntToScalar(advances[i]);
     74         }
     75         context->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, textRect, *paint);
     76     } else {
     77         SkAutoSTArray<kLocalGlyphMax * 2, SkScalar> storage(numGlyphs);
     78         SkScalar* xpos = storage.get();
     79         for (unsigned i = 0; i < numGlyphs; i++) {
     80             xpos[i] = x;
     81             x += SkIntToScalar(advances[i]);
     82         }
     83         context->drawPosTextH(glyphs, numGlyphs * sizeof(uint16_t),
     84                              xpos, y, textRect, *paint);
     85     }
     86 }
     87 
     88 static void paintSkiaText(GraphicsContext* context,
     89     const FontPlatformData& data,
     90     SkTypeface* face, float size, uint32_t textFlags,
     91     unsigned numGlyphs,
     92     const WORD* glyphs,
     93     const int* advances,
     94     const GOFFSET* offsets,
     95     const SkPoint& origin,
     96     const SkRect& textRect)
     97 {
     98     TextDrawingModeFlags textMode = context->textDrawingMode();
     99 
    100     // Filling (if necessary). This is the common case.
    101     SkPaint paint;
    102     context->setupPaintForFilling(&paint);
    103     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    104     data.setupPaint(&paint, context);
    105 
    106     // FIXME: Only needed to support the HFONT based paintSkiaText
    107     // version where a new typeface is created from the HFONT.
    108     // As such it can go away once the HFONT code path is removed.
    109     paint.setTypeface(face);
    110 
    111     bool didFill = false;
    112 
    113     if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
    114         skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
    115         didFill = true;
    116     }
    117 
    118     // Stroking on top (if necessary).
    119     if ((textMode & TextModeStroke)
    120         && context->strokeStyle() != NoStroke
    121         && context->strokeThickness() > 0) {
    122 
    123         paint.reset();
    124         context->setupPaintForStroking(&paint);
    125         paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    126         data.setupPaint(&paint, context);
    127         paint.setTypeface(face);
    128 
    129         if (didFill) {
    130             // If there is a shadow and we filled above, there will already be
    131             // a shadow. We don't want to draw it again or it will be too dark
    132             // and it will go on top of the fill.
    133             //
    134             // Note that this isn't strictly correct, since the stroke could be
    135             // very thick and the shadow wouldn't account for this. The "right"
    136             // thing would be to draw to a new layer and then draw that layer
    137             // with a shadow. But this is a lot of extra work for something
    138             // that isn't normally an issue.
    139             paint.setLooper(0);
    140         }
    141 
    142         skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
    143     }
    144 }
    145 
    146 ///////////////////////////////////////////////////////////////////////////////////////////
    147 
    148 void paintSkiaText(GraphicsContext* context,
    149     const FontPlatformData& data,
    150     unsigned numGlyphs,
    151     const WORD* glyphs,
    152     const int* advances,
    153     const GOFFSET* offsets,
    154     const SkPoint& origin,
    155     const SkRect& textRect)
    156 {
    157     paintSkiaText(context, data, data.typeface(), data.size(), data.paintTextFlags(),
    158                   numGlyphs, glyphs, advances, offsets, origin, textRect);
    159 }
    160 #if !USE(HARFBUZZ)
    161 void paintSkiaText(GraphicsContext* context,
    162     const FontPlatformData& data,
    163     HFONT hfont,
    164     unsigned numGlyphs,
    165     const WORD* glyphs,
    166     const int* advances,
    167     const GOFFSET* offsets,
    168     const SkPoint& origin,
    169     const SkRect& textRect)
    170 {
    171     int size;
    172     int paintTextFlags = data->paintTextFlags();
    173 
    174     // Ensure font load for printing, because PDF device needs it.
    175     if (context->isPrintingDevice())
    176         FontPlatformData::ensureFontLoaded(hfont);
    177 
    178     RefPtr<SkTypeface> face = CreateTypefaceFromHFont(hfont, &size, &paintTextFlags);
    179     paintSkiaText(context, data, face.get(), size, paintTextFlags, numGlyphs, glyphs, advances, offsets, origin, textRect);
    180 }
    181 #endif
    182 }  // namespace WebCore
    183