diff options
Diffstat (limited to 'WebCore/platform/graphics/android/FontAndroid.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/FontAndroid.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/WebCore/platform/graphics/android/FontAndroid.cpp b/WebCore/platform/graphics/android/FontAndroid.cpp new file mode 100644 index 0000000..54a1a08 --- /dev/null +++ b/WebCore/platform/graphics/android/FontAndroid.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Font.h" + +#include "FontData.h" +#include "FontFallbackList.h" +#include "GraphicsContext.h" +#include "GlyphBuffer.h" +#include "PlatformGraphicsContext.h" +#include "IntRect.h" + +#include "SkCanvas.h" +#include "SkLayerDrawLooper.h" +#include "SkPaint.h" +#include "SkTemplates.h" +#include "SkTypeface.h" +#include "SkUtils.h" + +namespace WebCore { + +static void updateForFont(SkPaint* paint, const SimpleFontData* font) { + font->platformData().setupPaint(paint); + paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); +} + +static SkPaint* setupFill(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + gc->setupFillPaint(paint); + updateForFont(paint, font); + return paint; +} + +static SkPaint* setupStroke(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + gc->setupStrokePaint(paint); + updateForFont(paint, font); + return paint; +} + +static bool setupForText(SkPaint* paint, GraphicsContext* gc, + const SimpleFontData* font) { + int mode = gc->textDrawingMode(); + + if ((mode & (cTextFill | cTextStroke)) == (cTextFill | cTextStroke)) { + SkLayerDrawLooper* looper = new SkLayerDrawLooper; + paint->setLooper(looper)->unref(); + + // we clear the looper, in case we have a shadow + + SkPaint* fillP = NULL; + SkPaint* strokeP = NULL; + if (gc->willStroke()) { + strokeP = setupStroke(looper->addLayer(), gc, font); + strokeP->setLooper(NULL); + } + if (gc->willFill()) { + fillP = setupFill(looper->addLayer(), gc, font); + fillP->setLooper(NULL); + } + + SkPaint shadowPaint; + SkPoint offset; + if (gc->setupShadowPaint(&shadowPaint, &offset)) { + SkPaint* p = looper->addLayer(offset.fX, offset.fY); + *p = shadowPaint; + if (strokeP && !fillP) { + // stroke the shadow if we have stroke but no fill + p->setStyle(SkPaint::kStroke_Style); + p->setStrokeWidth(strokeP->getStrokeWidth()); + } + updateForFont(p, font); + } + } else if (mode & cTextFill) { + (void)setupFill(paint, gc, font); + } else if (mode & cTextStroke) { + (void)setupStroke(paint, gc, font); + } else { + return false; + } + return true; +} + +void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, + const GlyphBuffer& glyphBuffer, int from, int numGlyphs, + const FloatPoint& point) const { + SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert + + SkPaint paint; + if (!setupForText(&paint, gc, font)) { + return; + } + + SkScalar x = SkFloatToScalar(point.x()); + SkScalar y = SkFloatToScalar(point.y()); + const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from); + const GlyphBufferAdvance* adv = glyphBuffer.advances(from); + SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); + SkPoint* pos = storage.get(); + + /* We need an array of [x,y,x,y,x,y,...], but webkit is giving us + point.xy + [width, height, width, height, ...], so we have to convert + */ + for (int i = 0; i < numGlyphs; i++) { + pos[i].set(x, y); + x += SkFloatToScalar(adv[i].width()); + y += SkFloatToScalar(adv[i].height()); + } + + SkCanvas* canvas = gc->platformContext()->mCanvas; + canvas->drawPosText(glyphs, numGlyphs * sizeof(*glyphs), pos, paint); +} + +FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int, int) const +{ + SkPaint paint; + SkScalar width, left; + SkPaint::FontMetrics metrics; + + primaryFont()->platformData().setupPaint(&paint); + + width = paint.measureText(run.characters(), run.length() << 1); + SkScalar spacing = paint.getFontMetrics(&metrics); + + return FloatRect(point.x(), + point.y() - floorf(SkScalarToFloat(-metrics.fAscent)), + roundf(SkScalarToFloat(width)), + roundf(SkScalarToFloat(spacing))); +} + +void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, FloatPoint const& point, int, int) const +{ + SkCanvas* canvas = gc->platformContext()->mCanvas; + SkPaint paint; + + if (!setupForText(&paint, gc, primaryFont())) { + return; + } + + // go to chars, instead of glyphs, which was set by setupForText() + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + + canvas->drawText(run.characters(), run.length() << 1, + SkFloatToScalar(point.x()), SkFloatToScalar(point.y()), + paint); +} + +float Font::floatWidthForComplexText(const TextRun& run) const +{ + SkPaint paint; + + primaryFont()->platformData().setupPaint(&paint); + +//printf("--------- complext measure %d chars\n", run.to() - run.from()); + + SkScalar width = paint.measureText(run.characters(), run.length() << 1); + return SkScalarToFloat(width); +} + +int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const +{ + SkPaint paint; + int count = run.length(); + SkAutoSTMalloc<64, SkScalar> storage(count); + SkScalar* widths = storage.get(); + + primaryFont()->platformData().setupPaint(&paint); + + count = paint.getTextWidths(run.characters(), count << 1, widths); + + if (count > 0) + { + SkScalar pos = 0; + for (int i = 0; i < count; i++) + { + if (x < SkScalarRound(pos + SkScalarHalf(widths[i]))) + return i; + pos += widths[i]; + } + } + return count; +} + +} |