Freigeben über


Layout.cpp

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
//----------------------------------------------------------------------------

#include "Common.h"
#include "CustomFont.h"
#include "Layout.h"
#include "resource.h"

float const Layout::leftMargin_     = 0.25f * 96;
float const Layout::rightMargin_    = 0.25f * 96;
float const Layout::minColumnWidth_ = 3.0f  * 96;

struct Layout::Format
{
    float pointSize;
    float spaceBefore;
    wchar_t const* familyName;
};

Layout::Format const Layout::formats_[] =
{
    { 20.0f, 12.0f, L"Pericles" },
    { 11.0f, 11.0f, L"Kootenay" }
};

UINT const Layout::paragraphs_[] =
{
    IDS_HEADING,
    IDS_BODY1,
    IDS_BODY2,
    IDS_BODY3
};

HRESULT Layout::Draw(float pageWidthInDips, ID2D1RenderTarget* renderTarget, ID2D1Brush* textBrush)
{
    HRESULT hr = S_OK;

    static UINT const fontResourceIDs[] = {  IDR_FONT_PERICLES, IDR_FONT_KOOTENAY };

    // Create a custom font collection comprising our two font resources. We could have done this
    // in the constructor rather than every time. However, if you set break points on the loader 
    // callbacks you'll find they're only called the first time the font collection is created. 
    // Thereafter the font collection data is cached so recreating it is quite fast.
    hr = fontContext_.Initialize();
    if (FAILED(hr))
        return hr;

    IDWriteFontCollection* fontCollection = NULL;
    hr = fontContext_.CreateFontCollection(
            fontResourceIDs,
            sizeof(fontResourceIDs),
            &fontCollection
            );
    if (FAILED(hr))
        return hr;

    // Set up for first paragraph.
    float const columnWidth = std::max<float>(minColumnWidth_, pageWidthInDips - leftMargin_ - rightMargin_);
    float y = 0;

    float spaceBefore = 0;
    IDWriteTextFormat* textFormat = NULL;

    size_t const formatCount = sizeof(formats_) / sizeof(formats_[0]);
    size_t const paragraphCount = sizeof(paragraphs_) / sizeof(paragraphs_[0]);

    // Iterate over all the paragraphs.
    for (size_t i = 0; i < paragraphCount; ++i)
    {
        // We create a different text format object for the first formatCount
        // paragraphs. After that we reuse the last text format object.
        if (i < formatCount)
        {
            // Create the text format object, specifying both the family name and the
            // custom font collection in which to look for the family name. DirectWrite
            // will only look for the family name in the specified collection so there
            // is no ambiguity even if the system font collection happens to have a font
            // with the same family name.
            SafeRelease(&textFormat);
            hr = g_dwriteFactory->CreateTextFormat(
                    formats_[i].familyName,
                    fontCollection,
                    DWRITE_FONT_WEIGHT_NORMAL,
                    DWRITE_FONT_STYLE_NORMAL,
                    DWRITE_FONT_STRETCH_NORMAL,
                    formats_[i].pointSize * (96.0f / 72),
                    L"en-us",
                    &textFormat
                    );

            spaceBefore = formats_[i].spaceBefore * (96.0f / 72);
        }

        IDWriteTextLayout* textLayout = NULL;
        if (SUCCEEDED(hr))
        {
            // Load the string.
            int const maxLength = 512;
            wchar_t charBuffer[maxLength];
            int stringLength = LoadString(g_instance, paragraphs_[i], charBuffer, maxLength);

            // Create the text layout object.
            hr = g_dwriteFactory->CreateTextLayout(
                    charBuffer,
                    stringLength,
                    textFormat,
                    columnWidth,
                    0,
                    &textLayout
                    );
        }

        if (SUCCEEDED(hr))
        {
            // Draw the text and update the y coordinate.
            y += spaceBefore;

            renderTarget->DrawTextLayout(
                D2D1::Point2F(leftMargin_, y),
                textLayout,
                textBrush
                );

            DWRITE_TEXT_METRICS metrics;
            hr = textLayout->GetMetrics(&metrics);
            y += metrics.height;
        }
        SafeRelease(&textLayout);

        if (FAILED(hr))
            break;
    }

    SafeRelease(&textFormat);
    SafeRelease(&fontCollection);

    return hr;
}